2017-03-08 106 views
0

我有以下XML文件:移動到其他節點XML節點,如果他們的一些節點的值相等(使用XSLT)

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <cases> 
     <case> 
     <key>123</key> 
     </case> 
     <case> 
     <key>456</key> 
     </case> 
    </cases> 
    <issues> 
     <issue> 
     <issueid>issue1</issueid> 
     <casekey>123</casekey> 
     </issue> 
     <issue> 
     <issueid>issue2</issueid> 
     <casekey>123</casekey> 
     </issue> 
     <issue> 
     <issueid>issue3</issueid> 
     <casekey>456</casekey> 
     </issue> 
    </issues> 
</root> 

我想所有的<issue>節點移動到<case><casekey>值相等到<key>的值爲<case>

換句話說,如果一個<issue><casekey>值等於到的<case><key>值,然後移動issuecase

我最終的XML應該如下:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <cases> 
     <case> 
     <key>123</key> 
     <issue> 
      <issueid>issue1</issueid> 
      <casekey>123</casekey> 
     </issue> 
     <issue> 
      <issueid>issue2</issueid> 
      <casekey>123</casekey> 
     </issue> 
     </case> 
     <case> 
     <key>456</key> 
     <issue> 
      <issueid>issue3</issueid> 
      <casekey>456</casekey> 
     </issue> 
     </case> 
    </cases> 
</root> 

回答

1

XSLT有一個內置的key機制,解決交叉引用 - 這是最好的使用方法:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="issues" match="issue" use="casekey" /> 

<xsl:template match="/root"> 
    <root> 
     <cases> 
      <xsl:for-each select="cases/case"> 
       <case> 
        <xsl:copy-of select="key"/> 
        <xsl:copy-of select="key('issues', key)"/> 
       </case> 
      </xsl:for-each> 
     </cases> 
     </root> 
</xsl:template> 

</xsl:stylesheet> 

P.S.不要混淆對XML中的key元素與xsl:key指令和key()函數的引用。

+0

超級!有趣的解決方案...! +1爲好的解決方案 –

1

主要的一點是匹配情況,包括模板:

  • 東西類似身份模板
  • 但在關閉之前xsl:copy還有另一個xsl:apply-templates, 來處理相應的問題。

最後要添加的是阻止「正常」處理問題標記。

下面你有一個工作的解決方案:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes" /> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="case"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:variable name="kk" select="key"/> 
     <xsl:apply-templates select="../../issues/issue[casekey=$kk]"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="issues"/> 

    <xsl:template match="@*|node()"> 
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy> 
    </xsl:template> 
</xsl:transform> 
+0

尼斯解釋。但michael.hor257k提供的解決方案似乎更簡單。 +1快速響應。謝謝。 –

1

<xsl:output method="xml" indent="yes"/> 

<xsl:template match="root"> 
    <root> 
     <xsl:apply-templates select="cases"/> 
    </root> 
</xsl:template> 

<xsl:template match="case"> 
    <xsl:variable name="keyvalue" select="normalize-space(key/text())"/> 

    <case> 
     <xsl:copy-of select="key"/> 
     <xsl:if test="ancestor::cases/following-sibling::issues/descendant::casekey = $keyvalue"> 
      <xsl:copy-of 
       select="ancestor::cases/following-sibling::issues/issue[casekey = $keyvalue]"/> 
     </xsl:if> 
    </case> 
</xsl:template> 

<xsl:template match="issue[child::casekey = preceding::key]"/> 


<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
</xsl:template> 

相關問題