2017-03-08 105 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> 

相关问题