XSLT 1.0如何在可选元素之后更新或插入元素

 2021-04-26 

XSLT 1.0 How to update or insert an element after an optional element

这类似于以下问题:XSLT-1.0:如何在相对于父元素的特定位置插入元素,但是那里的答案并不涵盖输入中缺少tag3的情况XML

我想在看起来如下的XML文档中插入或更新标签(例如tag4),除了tag1,tag2,tag3,tag4和tag5都是可选的。

1
2
3
4
5
6
7
<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag4 value="d" />
    <tag5 value="e" />
</Begin>

即以下是示例输入和输出

输入:

1
2
<Begin>
</Begin>

输出:

1
2
3
<Begin>
    <tag4 value="updated" />
</Begin>

输入:

1
2
3
<Begin>
    <tag4 value="d" />
</Begin>

输出:

1
2
3
<Begin>
    <tag4 value="updated" />
</Begin>

输入:

1
2
3
4
<Begin>
    <tag1 value="a" />
    <tag5 value="e" />
</Begin>

输出:

1
2
3
4
5
<Begin>
    <tag1 value="a" />
    <tag4 value="updated" />
    <tag5 value="e" />
</Begin>

输入:

1
2
3
4
5
<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag5 value="e" />
</Begin>

输出:

1
2
3
4
5
6
<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag4 value="updated" />
    <tag5 value="e" />
</Begin>

输入:

1
2
3
4
5
6
<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag5 value="e" />
</Begin>

输出:

1
2
3
4
5
6
7
<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag4 value="updated" />
    <tag5 value="e" />
</Begin>

更新

我还希望能够保留Begin或tag4元素上可能已经存在的所有属性,例如:

输入:

1
2
3
4
5
6
7
<Begin someAttribute="someValue">
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag4 value="d" someOtherAttribute="someOtherValue" />
    <tag5 value="e" />
</Begin>

输出:

1
2
3
4
5
6
7
<Begin someAttribute="someValue">
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag4 value="updated" someOtherAttribute="someOtherValue" />
    <tag5 value="e" />
</Begin>


尝试:

1
2
3
4
5
6
7
<xsl:template match="Begin">
  <Begin>
    <xsl:copy-of select="tag1 | tag2 | tag3"/>
    <tag4 value="updated"/>
    <xsl:copy-of select="tag5"/>
  </Begin>
</xsl:template>


尝试一下...如果需要,可以在调试器中对其进行跟踪以帮助您解决问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    <xsl:template match="Begin">
      <xsl:copy>
        <!-- Apply any attributes for Begin.  -->
        <xsl:apply-templates select="@*"/>

        <!-- Output the tag* nodes before tag4. -->
        <xsl:apply-templates select="tag1|tag2|tag3"/>

        <xsl:choose>
          <!-- Is there already a tag4? -->
          <xsl:when test="tag4">
            <xsl:apply-templates select="tag4"/>
          </xsl:when>
          <xsl:otherwise>
            <!-- Create tag4 -->
            <tag4 value="updated"/>
          </xsl:otherwise>
        </xsl:choose>

        <!-- Output the tag* nodes after tag4. -->
        <xsl:apply-templates select="tag5"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="tag4">
      <xsl:copy>
        <xsl:attribute name="value">d</xsl:attribute>
        <xsl:attribute name="someOtherAttribute">someOtherValue</xsl:attribute>
        <xsl:apply-templates select="node()"/>
      </xsl:copy>
    </xsl:template>

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