【问题标题】:XSLT 1.0 How to update or insert an element after an optional elementXSLT 1.0 如何在可选元素之后更新或插入元素
【发布时间】:2020-04-25 12:59:49
【问题描述】:

这类似于这个问题:XSLT-1.0: How to insert an element at a specific position with respect to the parent element,但那里的答案没有涵盖输入 XML 中缺少tag3 的情况

我想在 XML 文档中插入或更新一个标记(比如 tag4),如下所示,除了 tag1、tag2、tag3、tag4 和 tag5 都是可选的。

<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag4 value="d" />
    <tag5 value="e" />
</Begin>

即以下是示例输入和输出

输入:

<Begin>
</Begin>

输出:

<Begin>
    <tag4 value="updated" />
</Begin>

输入:

<Begin>
    <tag4 value="d" />
</Begin>

输出:

<Begin>
    <tag4 value="updated" />
</Begin>

输入:

<Begin>
    <tag1 value="a" />
    <tag5 value="e" />
</Begin>

输出:

<Begin>
    <tag1 value="a" />
    <tag4 value="updated" />
    <tag5 value="e" />
</Begin>

输入:

<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag5 value="e" />
</Begin>

输出:

<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag4 value="updated" />
    <tag5 value="e" />
</Begin>

输入:

<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag5 value="e" />
</Begin>

输出:

<Begin>
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag4 value="updated" />
    <tag5 value="e" />
</Begin>

更新

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

输入:

<Begin someAttribute="someValue">
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag4 value="d" someOtherAttribute="someOtherValue" />
    <tag5 value="e" />
</Begin>

输出:

<Begin someAttribute="someValue">
    <tag1 value="a" />
    <tag2 value="b" />
    <tag3 value="c" />
    <tag4 value="updated" someOtherAttribute="someOtherValue" />
    <tag5 value="e" />
</Begin>

【问题讨论】:

  • 你知道tag4元素上“可能已经存在”的属性的名称吗?
  • @michael.hor257k - 不,我不知道,它们可能会发生变化。所以我本质上想复制 tag4 元素,然后如果 tag4 元素存在则添加/更新我的“值”属性,如果不存在则创建它。
  • 然后复制tag4的所有属性并然后覆盖value属性,或者复制除value之外的所有属性。对于Begin 元素,您可以简单地将其所有属性复制到其任何子元素之前(或连同其第一批子元素)..
  • @michael.hor257k - 是的,这基本上就是我期望做的。 Michael Kay 已经给了我大部分我需要的东西,我相信我可以自己解决剩下的问题(除非他好心更新他的答案!)。完成此操作后,我将接受他的回答。
  • 我的建议是在凯博士给出的答案之上的。我会给你同样的答案(希望减去第 1 行的错字)。这是我提到的第二个选项的实现示例:xsltfiddle.liberty-development.net/ehVZvvV

标签: xslt xslt-1.0


【解决方案1】:

试试:

<xsl:template match="Begin">
  <Begin>
    <xsl:copy-of select="tag1 | tag2 | tag3"/>
    <tag4 value="updated"/>
    <xsl:copy-of select="tag5"/>
  </Begin>
</xsl:template>

【讨论】:

  • +1 这几乎是我所需要的,我也许可以自己解决剩下的问题。我没有提到(希望使示例尽可能简单)是我想保留任何标签 Begin 或 tag4 上可能已经存在的任何属性。我将更新其中一个示例以说明我的意思。
  • 这些问题与您提出的问题完全无关,因此如果您自己无法解决,请提出一个新问题。 (这没什么难的,如果你有问题,这表明你真的应该多读书。)
  • 你说的完全正确,我应该能够自己解决剩下的问题。我从您的简历中了解到您是 XSLT Programmers Reference 的作者,这是一本我在 17 年前读过的优秀书籍,直到最近我最后一次使用 XSLT。我可能应该买一本再读一遍。还看到您可能和我同时在 ICL 工作过(还记得 System 25 吗?)
【解决方案2】:

试一试...如果需要,请在调试器中跟踪它以帮助您解决问题。

    <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>

【讨论】:

  • 这看起来是个不错的方法,我会尝试一下。惊讶地看到它甚至没有评论的礼貌就被否决了,所以我会用赞成票取消它:)
猜你喜欢
  • 2016-12-03
  • 2011-01-16
  • 2021-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多