2012-09-20 190 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