2012-09-20 150 views
0

我无法转换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

不,您不会覆盖输入中的任何内容。 XSLT转换的输出树是与输入不同的对象,输入不可变。输入中的任何内容都不会被覆盖或更改。

是的,你是对的:你的问题有一个简单的解决方案。

的问题是,你的尝试/ ProcessMessages /消息的ExternalRefID和号码复制到RelatedMessages元素的结尾采取以下形式:

<xsl:apply-templates 
    select="//ProcessMessages 
      /Message/ExternalRefID"/> 
<xsl:apply-templates 
    select="//ProcessMessages 
      /Message/Number"/> 

样式表引擎也为你问,并寻求模板为那些元素。它会在您的示例代码中找到第二个和第三个模板,这些模板从相关消息中的最后一个Message元素中查找并复制值。

对于我来说,完全不清楚如何定义你想要构建的转换,但是如果你试图做的是(1)将相关消息的最终消息移动为第一个孩子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> 

如果你想要更改号码和ExternalRefID,那么你就需要适当修改此代码。

+0

感谢您的回答。我上周能够完成翻译,现在xsl正在使用。 – mRope