复制除XSLT中的所有子元素之外的所有子元素,而不复制整个XML

时间:2014-09-09 09:44:04

标签: xslt

我已经搜索过复制子元素,除了一个或更改标记的值。模板下面的所有地方都用于复制所有XML然后 应用模板删除一个元素。

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

<xsl:template match="part"/>

我有一个类似下面的XML

<root>
    <a1>
    ...
    </a1>
    <a2>
    ....
    </a2>
    <a3>
        <a31>1</a31>
        <a32>2</a32>
        <a33>
            <a331>3</a331>
            <a332>5</a332>
            ...
            <a339>10</a339>
        </a33>
        <a33>
            <a331>4</a331>
            <a332>6</a332>
            ...
            <a339>56</a339>
        </a33>
        <a34>
            <a331>3</a331>
            ....
        </a34>
    </a3>
</root>

我写过像这样的xslt

<xsl:template match="root">
    <xsl:element name="root">
        <xsl:apply-templates select="root"/>
    </xsl:element>
</xsl:template>

<xsl:template match="root">
    <xsl:element name="a1">
        <xsl:apply-templates select="a1"/>
    </xsl:element>
    ...
    <xsl:if test="a3!=''">
        <xsl:if test="((a3/a33[a331='3']!='') or (a3/a33[a331='3']!=''))">
            <xsl:element name="a3">
                <xsl:apply-templates select="a3"/>
            </xsl:elememt>
        </xsl:if>
    </xsl:if>
</xsl:template>

<xsl:template match="a3" >      
    <xsl:apply-templates select="*[a331='3']" mode="copy"></xsl:apply-templates>
</xsl:template>

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

<xsl:template match="a331">
    <xsl:element name="a331">
        <xsl:value-of select="4">
    </xsl:element>
</xsl:template>

我想得到如下的输出xml。

<root>
    <a1>
    ...
    </a1>
    <a2>
    ....
    </a2>
    <a3>
        <a31>1</a31>
        <a32>2</a32>
        <a33>
            <a331>4</a331>
            <a332>5</a332>
            ...
            <a339>10</a339>
        </a33>      
        <a34>
            <a331>4</a331>
            ....
        </a34>
    </a3>
</root>

你能否解释一下如何在不首先复制整个XML的情况下实现这一目标?

1 个答案:

答案 0 :(得分:2)

有两种基本的XSLT策略:从零开始并通过显式添加节点来构建输出,或者通过复制所有内容并仅添加更改来开始。毫无疑问,在你的情况下,后一种策略是更有效的策略。

如果我正确理解您的要求,您只想进行两次(相对较小的)更改:

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="a33[not(a331=3)]"/>

<xsl:template match="a331">
    <a331>4</a331>
</xsl:template>

</xsl:stylesheet>

应用于以下测试输入

<root>
    <a1/>
    <a2/>
    <a3>
        <a31>1</a31>
        <a32>2</a32>
        <a33>
            <a331>3</a331>
            <a332>5</a332>
            <a339>7</a339>
        </a33>
        <a33>
            <a331>4</a331>
            <a332>6</a332>
            <a339>8</a339>
        </a33>
        <a34>
            <a331>3</a331>
        </a34>
    </a3>
</root>

结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <a1/>
   <a2/>
   <a3>
      <a31>1</a31>
      <a32>2</a32>
      <a33>
         <a331>4</a331>
         <a332>5</a332>
         <a339>7</a339>
      </a33>
      <a34>
         <a331>4</a331>
      </a34>
   </a3>
</root>