使用XSLT 2将元素从一个地方移动到另一个地方

时间:2013-10-07 05:59:00

标签: xslt-2.0

使用XSLT 2(saxon8)将元素从一个地方移动到另一个地方

大家好,请帮我用XSLT 2.0生成以下输出。

我有这个:

<UL>
 <ITEM>
    aaa 
    <NL>iii
        <ITEM1>111</ITEM1>
        <ITEM2>222</ITEM2>
    </NL>
 </ITEM>
 <ITEM>
    bbb
    <NL>vvv
        <ITEM1>333</ITEM1>
        <ITEM2>444</ITEM2>
    </NL>
 </ITEM> 
</UL>

我需要制作这个

<UL>
 <ITEM>
    aaa
    <ITEM1>111</ITEM1>
 </ITEM>
 <ITEM>
    bbb
    <ITEM1>333</ITEM1>
 </ITEM>
 <NEW>
  <NL>iii
   <ITEM2>222</ITEM2>
  </NL> 
  <NL>vvv
   <ITEM2>444</ITEM2>
  </NL>
 </NEW>
</UL>

我正在尝试使用模式选项获取输出,如下所述:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="NL"/>
    <xsl:template match="ITEM2"/>

    <xsl:template match="UL">
      <xsl:copy>
    <xsl:apply-templates/>
    <NEW>
      <xsl:apply-templates select="descendant::NL" mode="move"/>
    </NEW>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="ITEM" mode="move">
        <xsl:copy>
            <xsl:apply-templates/>
        <xsl:apply-templates select="descendant::ITEM2" mode="move1"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="NL" mode="move">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>


    <xsl:template match="ITEM2" mode="move1">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet> 

谢谢和问候

巴拉

1 个答案:

答案 0 :(得分:0)

这是一个XSLT 2.0样式表,它可以创建你想要的结构,虽然空白区域不同,因为混合内容产生精确输出是一个问题:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:template match="UL">
        <xsl:copy>
            <xsl:for-each-group select="ITEM" group-by="NL/*/node-name(.)">
                <xsl:choose>
                    <xsl:when test="position() eq 1">
                        <xsl:for-each select="current-group()">
                            <ITEM>
                                <xsl:apply-templates select="text() | NL/*[node-name(.) eq current-grouping-key()]"/>
                            </ITEM>
                        </xsl:for-each>
                    </xsl:when>
                    <xsl:otherwise>
                        <NEW>
                            <xsl:for-each select="current-group()">
                                <NL>
                                    <xsl:apply-templates select="NL/(text() | *[node-name(.) eq current-grouping-key()])"/>
                                </NL>
                            </xsl:for-each>
                        </NEW>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="NL/*">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

我得到了结果

<UL><ITEM>
        aaa 
        <ITEM1>111</ITEM1>
    </ITEM><ITEM>
        bbb
        <ITEM1>333</ITEM1>
    </ITEM><NEW><NL>iii

            <ITEM2>222</ITEM2>
        </NL><NL>vvv

            <ITEM2>444</ITEM2>
        </NL></NEW></UL>

当我添加指令以从输入中去除空白区域并缩进输出时,如

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:template match="UL">
        <xsl:copy>
            <xsl:for-each-group select="ITEM" group-by="NL/*/node-name(.)">
                <xsl:choose>
                    <xsl:when test="position() eq 1">
                        <xsl:for-each select="current-group()">
                            <ITEM>
                                <xsl:apply-templates select="text() | NL/*[node-name(.) eq current-grouping-key()]"/>
                            </ITEM>
                        </xsl:for-each>
                    </xsl:when>
                    <xsl:otherwise>
                        <NEW>
                            <xsl:for-each select="current-group()">
                                <NL>
                                    <xsl:apply-templates select="NL/(text() | *[node-name(.) eq current-grouping-key()])"/>
                                </NL>
                            </xsl:for-each>
                        </NEW>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="NL/*">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

结果是

<UL>
   <ITEM>
        aaa 
        <ITEM1>111</ITEM1>
   </ITEM>
   <ITEM>
        bbb
        <ITEM1>333</ITEM1>
   </ITEM>
   <NEW>
      <NL>iii
            <ITEM2>222</ITEM2>
      </NL>
      <NL>vvv
            <ITEM2>444</ITEM2>
      </NL>
   </NEW>
</UL>

作为替代方案,如果我们知道我们想要拆分ITEM1ITEM2,那么这里是使用模式的样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="NL">
        <xsl:apply-templates select="ITEM1"/>
    </xsl:template>

    <xsl:template match="ITEM2"/>

    <xsl:template match="UL">
        <xsl:copy>
            <xsl:apply-templates/>
            <NEW>
                <xsl:apply-templates select="descendant::NL" mode="move"/>
            </NEW>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ITEM1" mode="move"/>

</xsl:stylesheet>