如果某些节点值相等,则将xml节点移动到其他节点(使用XSLT)

时间:2017-03-08 14:05:10

标签: xslt

我有以下xml文件:

<?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>的{​​{1}}值。

换句话说,如果<case>的{​​{1}}值等于<casekey>的{​​{1}}值,则将<issue>移到<key><case>

我的最终xml应如下所示:

issue

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分: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()函数混淆。

答案 2 :(得分: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>