XSLT:通过匹配属性值将节点数据复制到另一个节点,有效吗?

问题描述

我编码了 XSLT 以通过验证属性值将一个节点数据复制到另一个节点,我得到了所需的输出,但我很想知道是否有一种有效的方法可以做到这一点,或者这是唯一的方法它。 [我不是 XSLT 专家] 有人可以帮忙吗!!!

请立即使用此链接进行检查。 https://xsltfiddle.liberty-development.net/pNvtBH2/3

实际 XML:

<?xml version="1.0" encoding="utf-8" ?>
<section>
  <p>note 1 : <a href="test1">1</a></p>
  <p>note 2 : <a href="test2">2</a></p>
  <p>note 3 : <a href="test3">3</a></p>
  <note id="test1">hello one</note>
  <note id="test2">hello two</note>
  <note id="test3">hello <i>three</i></note>
  <note id="test4">hello <i>four</i></note>
</section>

输出

    <?xml version="1.0" encoding="UTF-8"?><section>
      <p>note 1 : <a>hello one</a></p>
      <p>note 2 : <a>hello two</a></p>
      <p>note 3 : <a>hello <i>three</i></a></p>
      
      
      
      <note id="test4">hello <i>four</i></note>
    </section>

XSLT 代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="#all"
    version="3.0">
  <xsl:output method="xml" />
  <xsl:template match="@*|node()">
      <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
  </xsl:template>

<xsl:template match="a">
<a>
    <xsl:variable name="href" select="@href" />
    <xsl:choose>
        <xsl:when test="$href = //note/@id">
            <xsl:copy-of select="//note[@id=$href]/node()" />
        </xsl:when>
    </xsl:choose>
</a>
</xsl:template>    

<xsl:template match="note">
    <xsl:choose>
        <xsl:when test="@id = //a/@href">
            <xsl:apply-templates select="node" />
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet> 

解决方法

它是否有效取决于您的 XSLT 处理器中的优化器的智能程度。 Saxon-EE 会在这方面做得很好,Saxon-HE 不太好。

如果您想在所有处理器上都高效,请使用密钥。将 //note[@id=$href] 之类的表达式替换为对 key() 函数的调用。将密钥声明为

<xsl:key name="k" match="note" use="id"/>

然后您可以使用 key('k',$href) 获取匹配的节点。

xsl:when test="$href = //note/@id" 是多余的,因为如果没有选择任何内容,xsl:copy-of 将什么也不做。

note 模板中,我不确定是什么

<xsl:when test="@id = //a/@href">
    <xsl:apply-templates select="node" />
</xsl:when>

正在尝试实现,因为您没有任何名为“node”的元素。如果目的是避免在此阶段处理已经从 a 元素处理过的音符元素,那么您可以使用

构建另一个索引
<xsl:key name="a" match="a" use="1"/>

并将 test="@id = //a/@href" 替换为 test="key('a',@href)"