首页 > 解决方案 > 使用 XPATH 选择两个处理指令之间的所有文本节点

问题描述

我有一些以下 XML:

<content>
  <p>
    <?change-addition-start?>
    test 
    <em>test</em>
    <strong>test</strong>
    <?change-addition-end?>
  </p>
</content>

我试图在 PI 之后添加一个<ins>标签,在<?change-addition-start?>PI 之前添加一个结束</ins>标签<?change-addition-end?>,所以基本上只是试图将这两个 PI 之间的任何内容包装在一个<ins>标签中。有没有办法通过 XSLT/XPATH 实现这一点?这些标签之间可以有任何内容,因此无法设置特定于我上面的测试用例的内容。

标签: xmlxsltxpathmarklogic

解决方案


我建议xal:for-each-group按照 Maring Honnen 的第一条评论中的建议使用。其他 XPath 方法允许您在两个处理指令之间选择内容,但是很难将其嵌入到应该做其他事情的 xslt 样式表中,例如同时复制现有结构。这是使用 for-each-group 的最小方法:

xquery version "1.0-ml";

let $xml :=
  <content>
    <p>
      before
      <?change-addition-start?>
      test 
      <em>test</em>
      <strong>test</strong>
      <?change-addition-end?>
      after
    </p>
  </content>

let $xsl :=
  <xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

    <xsl:template match="*[processing-instruction()]">
      <xsl:variable name="parent" select="." />

      <xsl:for-each-group select="node()" group-starting-with="processing-instruction()">
        <xsl:choose>
          <xsl:when test="self::processing-instruction('change-addition-start')">
            <ins>
              <xsl:apply-templates select="current-group()" mode="identity"/>
            </ins>
          </xsl:when>

          <xsl:otherwise>
            <xsl:apply-templates select="current-group()" mode="identity"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:template>

  </xsl:stylesheet>

return xdmp:xslt-eval($xsl, $xml)

如果您想在标签获取结束 PI,请按照 Martin 的建议使用带有 group-ending-by 的第二个 for-each-group 。<ins>不过,以上可能就足够了。


推荐阅读