我无法转换XML消息的某些元素。我需要交换一些值,但在我将最后一个节点的值复制到第一个节点之后,我无法达到第一个节点的原始值。
我一直在寻找几个小时,我在XSL中尝试了几种变体,但没有一个给出令人满意的结果。我不是一个非常有经验的XSL程序员,但我相信解决方案不会那么困难。我简化了原始信息以解释问题,我希望你们中的一个可以帮助我解决这个问题。让我通过以下例子解释:
来源:
<ProcessMessages>
<Message>
<SomeNode>Val</SomeNode>
<SomeNode>Val</SomeNode>
<Number>100000</Number>
<ExternalRefID>EXX12345600000001</ExternalRefID>
<SomeNode>Val</SomeNode>
<SomeNode>Val</SomeNode>
</Message>
<RelatedMessages>
<Message>
<SomeNode>Val</SomeNode>
<Number>200000</Number>
<ExternalRefID>EXX12345600000002</ExternalRefID>
<SomeNode>Val</SomeNode>
</Message>
<Message>
<SomeNode>Val</SomeNode>
<Number>300000</Number>
<ExternalRefID>EXX12345600000003</ExternalRefID>
<SomeNode>Val</SomeNode>
</Message>
</RelatedMessages>
</ProcessMessages>
期望的转型:
<ProcessMessages>
<Message>
<SomeNode>Val</SomeNode>
<SomeNode>Val</SomeNode>
<ExternalRefID>EXX12345600000003</ExternalRefID>
<SomeNode>Val</SomeNode>
<SomeNode>Val</SomeNode>
</Message>
<RelatedMessages>
<Message>
<Number>200000</Number>
<ExternalRefID>EXX12345600000002</ExternalRefID>
</Message>
<Message>
<Number>100000</Number>
<ExternalRefID>EXX12345600000001</ExternalRefID>
</Message>
</RelatedMessages>
</ProcessMessages>
我的XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//ProcessMessages/Message/ExternalRefID">
<xsl:apply-templates select="//ProcessMessages/RelatedMessages/Message[last()]/ExternalRefID"/>
</xsl:template>
<xsl:template match="//ProcessMessages/Message/Number">
<xsl:apply-templates select="//ProcessMessages/RelatedMessages/Message[last()]/Number"/>
</xsl:template>
<xsl:template match="//ProcessMessages/RelatedMessages/Message[1]">
<xsl:element name="Message">
<xsl:apply-templates select="ExternalRefID"/>
<xsl:apply-templates select="Number"/>
</xsl:element>
</xsl:template>
<xsl:template match="//ProcessMessages/RelatedMessages/Message[2]">
<xsl:element name="Message">
<xsl:apply-templates select="//ProcessMessages/Message/ExternalRefID"/>
<xsl:apply-templates select="//ProcessMessages/Message/Number"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
当前结果
<ProcessMessages>
<Message>
<SomeNode>Val</SomeNode>
<SomeNode>Val</SomeNode>
<Number>100000</Number>
<ExternalRefID>EXX12345600000001</ExternalRefID>
<SomeNode>Val</SomeNode>
<SomeNode>Val</SomeNode>
</Message>
<RelatedMessages>
<Message>
<ExternalRefID>EXX12345600000002</ExternalRefID>
<Number>200000</Number>
</Message>
<Message>
<ExternalRefID>EXX12345600000001</ExternalRefID>
<Number>100000</Number>
</Message>
</RelatedMessages>
</ProcessMessages>
请注意,将ProcessMessages/RelatedMessages/Message
的值复制到ProcessMessages/Message
后,我无法达到默认值ProcessMessages/Message
,因为它似乎被覆盖了。
有什么想法吗?如果有人可以帮助我,我将非常感激!
答案 0 :(得分:0)
不,你没有覆盖输入中的任何内容。 XSLT转换的输出树是输入的单独对象,输入不可变。输入中的任何内容都不会被覆盖或更改。
是的,你是对的:你的问题有一个简单的解决方案。
问题是您尝试将ExternalRefID和Number of / ProcessMessages / Message复制到RelatedMessages元素的末尾采用以下形式:
<xsl:apply-templates
select="//ProcessMessages
/Message/ExternalRefID"/>
<xsl:apply-templates
select="//ProcessMessages
/Message/Number"/>
样式表引擎按您的要求执行,并为这些元素寻找模板。它在示例代码中找到第二个和第三个模板,这些模板从相关消息中的最后一个Message元素中查找和复制值。
我并不完全清楚如何定义您正在尝试构建的转换,但 if 您要尝试做的是(1)将RelatedMessages的最终消息移动到ProcessMessages的第一个子节点,以及(2)将ProcessMessages的第一个子节点移动到RelatedMessages的末尾,那么这样的东西就可以工作:
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ProcessMessages">
<xsl:copy-of
select="RelatedMessages/Message[last()]"/>
<xsl:apply-templates select="RelatedMessages"/>
</xsl:template>
<xsl:template
match="RelatedMessages/Message[last()]">
<xsl:copy-of
select="../../self::ProcessMessages
/Message[1]"/>
</xsl:template>
如果您只想 更改Number和ExternalRefID,那么您需要适当修改此代码。