XSL:如何拆分具有给定子元素的元素

时间:2016-09-02 15:23:47

标签: xml xslt

我有一些这样的XML

<a>
  <b attr = 'foo'>
    <d>text</d>
    <x attr1 = 'foo1'>x-text-1</x>
    <x>x-text-2</x>
    <e attr2 = 'foo2' />
  </b>
</a>

我需要将以<a>为根的整个树分成两个(或更多)树,结构相同,但每个副本只有一个<x>

<a>
  <b attr = 'foo'>
    <d>text</d>
    <x attr1 = 'foo1'>x-text-1</x>
    <e attr2 = 'foo2' />
  </b>
</a>

<a>
  <b attr = 'foo'>
    <d>text</d>
    <x>x-text-2</x>
    <e attr2 = 'foo2' />
  </b>
</a>

两个新的<a>节点将包含在另一个父节点中。除了a/b/x路径的存在,我不知道有关该结构的任何其他信息(即<a>或任何其他节点,包括<x>,可能包含我不知道的节点和所有节点可能都有我不知道的属性。

我试图弄清楚如何在XSL中做到这一点,但我真的没有一个具体的想法。我只能想到for-each over all a/b/x然后从a/开始的副本,并且排除x不等于当前考虑的那个 - {1}}每次迭代。但是,尝试在XSL中编写这个想法,我感到头疼,任何帮助都是值得赞赏的。

1 个答案:

答案 0 :(得分:2)

  

我需要将以<a>为根的整个树分成两个(或更多)   树,具有相同的结构,但每个副本只有一个<x>

以这种方式试试吗?

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:template match="/">
    <root>
        <xsl:for-each select="//x">
            <xsl:apply-templates select="/*">
                <xsl:with-param name="x-id" select="generate-id()"/>
            </xsl:apply-templates>
        </xsl:for-each>
    </root>
</xsl:template>   

<!-- modified identity tranform -->
<xsl:template match="@*|node()">
    <xsl:param name="x-id" />
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:with-param name="x-id" select="$x-id"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="x">
    <xsl:param name="x-id" />
    <xsl:if test="generate-id() = $x-id">
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <a>
      <b attr="foo">
         <d>text</d>
         <x attr1="foo1">x-text-1</x>
         <e attr2="foo2"/>
      </b>
   </a>
   <a>
      <b attr="foo">
         <d>text</d>
         <x>x-text-2</x>
         <e attr2="foo2"/>
      </b>
   </a>
</root>