将元素移动到元素外部

时间:2015-06-23 09:30:15

标签: xslt

我必须做以下事情:

<A>Something <B>something else</B> more</A>

应该成为

<A>Something </A><B>something else</B><A> more</A>

即。每当<B>作为<A>的直接子项出现时,<A>应该关闭,<B>应该在<A>之外,并在<B>之后{1}} <A>应该再次打开。

实现这一目标的最简单方法是什么?

编辑:

<A>Something <C>anything</C><B>something</B> foo</A>

应该成为

<A>Something <C>anything</C></A><B>something</B><A> foo</A>

即。 <B>个元素和<B>个元素应该从其直接<A>个父元素中释放。

2 个答案:

答案 0 :(得分:2)

以下样式表将在应用于您的示例时返回请求的结果。

但是,正如我在对您的问题的评论中所说,有许多可能的情况,您的问题没有涵盖。具体来说,A的其他孩子应该发生什么,既不是B也不是文本节点。

另请注意,如果A是根元素(如示例所示),则结果将是格式错误的XML文档。

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="*"/>

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

<xsl:template match="A[B]">
    <xsl:apply-templates select="@*|node()"/>
</xsl:template>

<xsl:template match="A[B]/text()">
    <A>
        <xsl:value-of select="."/>
    </A>
</xsl:template>

</xsl:stylesheet>

测试输入:

<root>
    <A>Something <B>something else</B> more</A>
    <A>Something <B>something else</B> <C>altogether</C> more</A>
    <A>Something more</A>
    <A>Something <C>altogether</C> more</A>
</root>

<强>结果

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <A>Something </A>
   <B>something else</B>
   <A> more</A>
   <A>Something </A>
   <B>something else</B>
   <C>altogether</C>
   <A> more</A>
   <A>Something more</A>
   <A>Something <C>altogether</C> more</A>
</root>

修改

如果我更了解你的要求(完全不确定),你想做的事情如下:

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="*"/>

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

<xsl:template match="A[B]">
    <xsl:apply-templates select="B"/>
</xsl:template>

<xsl:template match="A/B">
    <xsl:variable name="i" select="position()" />
    <xsl:if test="$i=1">
        <xsl:variable name="first-group" select="preceding-sibling::node()"/>
        <xsl:if test="$first-group">
            <A>
                <xsl:copy-of select="$first-group"/>
            </A>
        </xsl:if>
    </xsl:if>
    <xsl:copy-of select="."/>
    <xsl:variable name="this-group" select="following-sibling::node()[not(self::B) and count(preceding-sibling::B)=$i]"/>
    <xsl:if test="$this-group">
        <A>
            <xsl:copy-of select="$this-group"/>
        </A>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:-1)

您可以尝试这样的事情

$p