使用xslt从xpath语句列表中注释xml实例

使用xslt从xpath语句列表中注释xml实例,xslt,xpath,xslt-2.0,Xslt,Xpath,Xslt 2.0,给定一个xpath语句列表,我想编写一个样式表,它将运行一个xml文档并输出同一个文档,但在每个xpath语句中标识的节点之前插入注释。让我们举个例子。从包含xpath语句的xml实例开始: <paths> <xpath location="/root/a" annotate="1"/> <xpath location="/root/a/b" annotate="2"/> </paths> 根据输入: <root> &

给定一个xpath语句列表,我想编写一个样式表,它将运行一个xml文档并输出同一个文档,但在每个xpath语句中标识的节点之前插入注释。让我们举个例子。从包含xpath语句的xml实例开始:

<paths>
  <xpath location="/root/a" annotate="1"/>
  <xpath location="/root/a/b" annotate="2"/>
</paths>

根据输入:

<root>
  <a>
    <b>B</b>
  </a>
  <c>C</c>
</root>

B
C
它应产生:

<root>
  <!-- 1 -->
  <a>
    <!-- 2 -->
    <b>B</b>
  </a>
  <c>C</c>
</root>

B
C
我最初的想法是创建一个标识样式表,它接受一个
文件列表
参数,调用其上的
文档
函数来获取xpath节点列表。然后,它将对照该列表检查输入的每个节点,然后在找到注释节点时插入注释节点,但我认为这可能会非常低效,因为XPath列表越来越大(或者可能不是,告诉我,我使用的是saxon 9)


所以我的问题是:有没有一种有效的方法来做这样的事情?

概述:

<paths>
  <xpath location="/root/a" annotate="1"/>
  <xpath location="/root/a/b" annotate="2"/>
  <xpath location="/root/c[@x='123']" annotate="3"/>
</paths>
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/paths">
    <xsl:element name="xsl:stylesheet">
      <xsl:attribute name="version">1.0</xsl:attribute>
      <xsl:element name="xsl:output">
        <xsl:attribute name="method">xml</xsl:attribute>
        <xsl:attribute name="indent">yes</xsl:attribute>
      </xsl:element>
      <xsl:call-template name="gen_identity_template"/>
      <xsl:apply-templates select="xpath"/>
    </xsl:element>
  </xsl:template>

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

  <xsl:template match="xpath">
    <xsl:element name="xsl:template">
      <xsl:attribute name="match">
        <xsl:value-of select="@location"/>
      </xsl:attribute>
      <xsl:element name="xsl:comment">
        <xsl:value-of select="@annotate"/>
      </xsl:element>
      <xsl:element name="xsl:text">
        <xsl:text disable-output-escaping="yes">&amp;#xa;</xsl:text>
      </xsl:element>
      <xsl:element name="xsl:copy">
        <xsl:element name="xsl:apply-templates">
          <xsl:attribute name="select">node()|@*</xsl:attribute>
        </xsl:element>
      </xsl:element>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" indent="yes"/>
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="/root/a">
      <xsl:comment>1</xsl:comment>
      <xsl:text>&#xa;</xsl:text>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="/root/a/b">
      <xsl:comment>2</xsl:comment>
      <xsl:text>&#xa;</xsl:text>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="/root/c[@x='123']">
      <xsl:comment>3</xsl:comment>
      <xsl:text>&#xa;</xsl:text>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>
<root>
  <a>
    <b>B</b>
  </a>
  <c x="123">C</c>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <!--1-->
   <a>
    <!--2-->
      <b>B</b>
  </a>
  <!--3-->
   <c x="123">C</c>
</root>
编写一个元XSLT转换,将
路径
文件作为输入,并生成一个新的XSLT转换作为输出。这个新的XSLT将从
输入XML转换为带注释的副本输出XML

注意事项:

<paths>
  <xpath location="/root/a" annotate="1"/>
  <xpath location="/root/a/b" annotate="2"/>
  <xpath location="/root/c[@x='123']" annotate="3"/>
</paths>
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/paths">
    <xsl:element name="xsl:stylesheet">
      <xsl:attribute name="version">1.0</xsl:attribute>
      <xsl:element name="xsl:output">
        <xsl:attribute name="method">xml</xsl:attribute>
        <xsl:attribute name="indent">yes</xsl:attribute>
      </xsl:element>
      <xsl:call-template name="gen_identity_template"/>
      <xsl:apply-templates select="xpath"/>
    </xsl:element>
  </xsl:template>

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

  <xsl:template match="xpath">
    <xsl:element name="xsl:template">
      <xsl:attribute name="match">
        <xsl:value-of select="@location"/>
      </xsl:attribute>
      <xsl:element name="xsl:comment">
        <xsl:value-of select="@annotate"/>
      </xsl:element>
      <xsl:element name="xsl:text">
        <xsl:text disable-output-escaping="yes">&amp;#xa;</xsl:text>
      </xsl:element>
      <xsl:element name="xsl:copy">
        <xsl:element name="xsl:apply-templates">
          <xsl:attribute name="select">node()|@*</xsl:attribute>
        </xsl:element>
      </xsl:element>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" indent="yes"/>
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="/root/a">
      <xsl:comment>1</xsl:comment>
      <xsl:text>&#xa;</xsl:text>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="/root/a/b">
      <xsl:comment>2</xsl:comment>
      <xsl:text>&#xa;</xsl:text>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="/root/c[@x='123']">
      <xsl:comment>3</xsl:comment>
      <xsl:text>&#xa;</xsl:text>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>
<root>
  <a>
    <b>B</b>
  </a>
  <c x="123">C</c>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <!--1-->
   <a>
    <!--2-->
      <b>B</b>
  </a>
  <!--3-->
   <c x="123">C</c>
</root>
  • 使用XSLT1.0、2.0或3.0
  • 应该是非常有效的,特别是如果 转换必须在大量输入上运行,或者必须运行 重复,因为它有效地编译为本机XSLT,而不是 而不是使用基于XSLT的解释器重新实现匹配
  • 比必须重建的方法更健壮 在代码中手动创建元素祖先。因为它将路径映射到
    template/@match
    属性,
    @match
    ing的完整复杂性 可以高效地使用。我已经包括了一个属性值测试 举个例子
  • <>请务必考虑优雅的XSLT 2和3解决方案 和@MartinHonnen,特别是如果中间的元XSLT文件 对你不起作用。通过利用XSLT 3.0的XPath计算 @MartinHonnen的回答似乎能够提供便利 甚至比这里的
    template/@match
    更健壮的匹配 此输入XML指定XPath和批注:

    <paths>
      <xpath location="/root/a" annotate="1"/>
      <xpath location="/root/a/b" annotate="2"/>
      <xpath location="/root/c[@x='123']" annotate="3"/>
    </paths>
    
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="/paths">
        <xsl:element name="xsl:stylesheet">
          <xsl:attribute name="version">1.0</xsl:attribute>
          <xsl:element name="xsl:output">
            <xsl:attribute name="method">xml</xsl:attribute>
            <xsl:attribute name="indent">yes</xsl:attribute>
          </xsl:element>
          <xsl:call-template name="gen_identity_template"/>
          <xsl:apply-templates select="xpath"/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template name="gen_identity_template">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">node()|@*</xsl:attribute>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="xpath">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">
            <xsl:value-of select="@location"/>
          </xsl:attribute>
          <xsl:element name="xsl:comment">
            <xsl:value-of select="@annotate"/>
          </xsl:element>
          <xsl:element name="xsl:text">
            <xsl:text disable-output-escaping="yes">&amp;#xa;</xsl:text>
          </xsl:element>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    </xsl:stylesheet>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
       <xsl:output method="xml" indent="yes"/>
       <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a">
          <xsl:comment>1</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a/b">
          <xsl:comment>2</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/c[@x='123']">
          <xsl:comment>3</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
    </xsl:stylesheet>
    
    <root>
      <a>
        <b>B</b>
      </a>
      <c x="123">C</c>
    </root>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <!--1-->
       <a>
        <!--2-->
          <b>B</b>
      </a>
      <!--3-->
       <c x="123">C</c>
    </root>
    
    
    
    当输入此元XSLT转换时:

    <paths>
      <xpath location="/root/a" annotate="1"/>
      <xpath location="/root/a/b" annotate="2"/>
      <xpath location="/root/c[@x='123']" annotate="3"/>
    </paths>
    
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="/paths">
        <xsl:element name="xsl:stylesheet">
          <xsl:attribute name="version">1.0</xsl:attribute>
          <xsl:element name="xsl:output">
            <xsl:attribute name="method">xml</xsl:attribute>
            <xsl:attribute name="indent">yes</xsl:attribute>
          </xsl:element>
          <xsl:call-template name="gen_identity_template"/>
          <xsl:apply-templates select="xpath"/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template name="gen_identity_template">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">node()|@*</xsl:attribute>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="xpath">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">
            <xsl:value-of select="@location"/>
          </xsl:attribute>
          <xsl:element name="xsl:comment">
            <xsl:value-of select="@annotate"/>
          </xsl:element>
          <xsl:element name="xsl:text">
            <xsl:text disable-output-escaping="yes">&amp;#xa;</xsl:text>
          </xsl:element>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    </xsl:stylesheet>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
       <xsl:output method="xml" indent="yes"/>
       <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a">
          <xsl:comment>1</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a/b">
          <xsl:comment>2</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/c[@x='123']">
          <xsl:comment>3</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
    </xsl:stylesheet>
    
    <root>
      <a>
        <b>B</b>
      </a>
      <c x="123">C</c>
    </root>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <!--1-->
       <a>
        <!--2-->
          <b>B</b>
      </a>
      <!--3-->
       <c x="123">C</c>
    </root>
    
    
    1
    xml
    对
    节点()|@*
    节点()|@*
    &#xa;
    节点()|@*
    
    将生成此XSLT转换:

    <paths>
      <xpath location="/root/a" annotate="1"/>
      <xpath location="/root/a/b" annotate="2"/>
      <xpath location="/root/c[@x='123']" annotate="3"/>
    </paths>
    
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="/paths">
        <xsl:element name="xsl:stylesheet">
          <xsl:attribute name="version">1.0</xsl:attribute>
          <xsl:element name="xsl:output">
            <xsl:attribute name="method">xml</xsl:attribute>
            <xsl:attribute name="indent">yes</xsl:attribute>
          </xsl:element>
          <xsl:call-template name="gen_identity_template"/>
          <xsl:apply-templates select="xpath"/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template name="gen_identity_template">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">node()|@*</xsl:attribute>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="xpath">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">
            <xsl:value-of select="@location"/>
          </xsl:attribute>
          <xsl:element name="xsl:comment">
            <xsl:value-of select="@annotate"/>
          </xsl:element>
          <xsl:element name="xsl:text">
            <xsl:text disable-output-escaping="yes">&amp;#xa;</xsl:text>
          </xsl:element>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    </xsl:stylesheet>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
       <xsl:output method="xml" indent="yes"/>
       <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a">
          <xsl:comment>1</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a/b">
          <xsl:comment>2</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/c[@x='123']">
          <xsl:comment>3</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
    </xsl:stylesheet>
    
    <root>
      <a>
        <b>B</b>
      </a>
      <c x="123">C</c>
    </root>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <!--1-->
       <a>
        <!--2-->
          <b>B</b>
      </a>
      <!--3-->
       <c x="123">C</c>
    </root>
    
    
    1.
    
    ;
    2.
    
    ;
    3.
    
    ;
    
    当提供此输入XML文件时:

    <paths>
      <xpath location="/root/a" annotate="1"/>
      <xpath location="/root/a/b" annotate="2"/>
      <xpath location="/root/c[@x='123']" annotate="3"/>
    </paths>
    
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="/paths">
        <xsl:element name="xsl:stylesheet">
          <xsl:attribute name="version">1.0</xsl:attribute>
          <xsl:element name="xsl:output">
            <xsl:attribute name="method">xml</xsl:attribute>
            <xsl:attribute name="indent">yes</xsl:attribute>
          </xsl:element>
          <xsl:call-template name="gen_identity_template"/>
          <xsl:apply-templates select="xpath"/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template name="gen_identity_template">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">node()|@*</xsl:attribute>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="xpath">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">
            <xsl:value-of select="@location"/>
          </xsl:attribute>
          <xsl:element name="xsl:comment">
            <xsl:value-of select="@annotate"/>
          </xsl:element>
          <xsl:element name="xsl:text">
            <xsl:text disable-output-escaping="yes">&amp;#xa;</xsl:text>
          </xsl:element>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    </xsl:stylesheet>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
       <xsl:output method="xml" indent="yes"/>
       <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a">
          <xsl:comment>1</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a/b">
          <xsl:comment>2</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/c[@x='123']">
          <xsl:comment>3</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
    </xsl:stylesheet>
    
    <root>
      <a>
        <b>B</b>
      </a>
      <c x="123">C</c>
    </root>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <!--1-->
       <a>
        <!--2-->
          <b>B</b>
      </a>
      <!--3-->
       <c x="123">C</c>
    </root>
    
    
    B
    C
    
    将生成所需的输出XML文件:

    <paths>
      <xpath location="/root/a" annotate="1"/>
      <xpath location="/root/a/b" annotate="2"/>
      <xpath location="/root/c[@x='123']" annotate="3"/>
    </paths>
    
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="/paths">
        <xsl:element name="xsl:stylesheet">
          <xsl:attribute name="version">1.0</xsl:attribute>
          <xsl:element name="xsl:output">
            <xsl:attribute name="method">xml</xsl:attribute>
            <xsl:attribute name="indent">yes</xsl:attribute>
          </xsl:element>
          <xsl:call-template name="gen_identity_template"/>
          <xsl:apply-templates select="xpath"/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template name="gen_identity_template">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">node()|@*</xsl:attribute>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="xpath">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">
            <xsl:value-of select="@location"/>
          </xsl:attribute>
          <xsl:element name="xsl:comment">
            <xsl:value-of select="@annotate"/>
          </xsl:element>
          <xsl:element name="xsl:text">
            <xsl:text disable-output-escaping="yes">&amp;#xa;</xsl:text>
          </xsl:element>
          <xsl:element name="xsl:copy">
            <xsl:element name="xsl:apply-templates">
              <xsl:attribute name="select">node()|@*</xsl:attribute>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
    </xsl:stylesheet>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
       <xsl:output method="xml" indent="yes"/>
       <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a">
          <xsl:comment>1</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/a/b">
          <xsl:comment>2</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
       <xsl:template match="/root/c[@x='123']">
          <xsl:comment>3</xsl:comment>
          <xsl:text>&#xa;</xsl:text>
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
       </xsl:template>
    </xsl:stylesheet>
    
    <root>
      <a>
        <b>B</b>
      </a>
      <c x="123">C</c>
    </root>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <!--1-->
       <a>
        <!--2-->
          <b>B</b>
      </a>
      <!--3-->
       <c x="123">C</c>
    </root>
    
    
    B
    C
    
    我不确定kjhughes关于创建第二个转换的建议是否比您最初的想法更有效。如果
    路径
    XML变大,我确实看到第二次转换的可能性变得巨大

    我会这样做的

    XML输入

    <root>
        <a>
            <b>B</b>
        </a>
        <c>C</c>
    </root>
    
    <root>
        <!--1-->
        <a>
            <!--2-->
            <b>B</b>
        </a>
        <c>C</c>
    </root>
    
    
    B
    C
    
    路径XML(path.XML)

    
    
    XSLT2.0

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:param name="paths" select="document('paths.xml')"/>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="*" priority="1">
            <xsl:variable name="path">
                <xsl:for-each select="ancestor-or-self::*">
                    <xsl:value-of select="concat('/',local-name())"/>
                </xsl:for-each>
            </xsl:variable>
            <xsl:if test="$paths/*/xpath[@location=$path]">
                <xsl:comment select="$paths/*/xpath[@location=$path]/@annotate"/>
            </xsl:if>
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
    </xsl:stylesheet>
    
    
    
    XML输出

    <root>
        <a>
            <b>B</b>
        </a>
        <c>C</c>
    </root>
    
    <root>
        <!--1-->
        <a>
            <!--2-->
            <b>B</b>
        </a>
        <c>C</c>
    </root>
    
    
    B
    C
    
    假设Saxon 9 PE或EE,也可以使用XSLT 3.0和
    xsl:evaluate
    ,如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:math="http://www.w3.org/2005/xpath-functions/math"
        xmlns:map="http://www.w3.org/2005/xpath-functions/map"
        xmlns:mf="http://example.com/mf"
        exclude-result-prefixes="xs math map mf"
        version="3.0">
    
        <xsl:output indent="yes"/>
    
        <xsl:param name="paths-url" as="xs:string" select="'paths1.xml'"/>
        <xsl:param name="paths-doc" as="document-node()" select="doc($paths-url)"/>
    
        <xsl:variable name="main-root" select="/"/>
    
        <xsl:variable 
            name="mapped-nodes">
            <map>
                <xsl:for-each select="$paths-doc/paths/xpath">
                    <xsl:variable name="node" as="node()?" select="mf:evaluate(@location, $main-root)"/>
                    <xsl:if test="$node">
                        <entry key="{generate-id($node)}">
                            <xsl:value-of select="@annotate"/>
                        </entry>
                    </xsl:if>
                </xsl:for-each>
            </map>
        </xsl:variable>
    
        <xsl:key name="node-by-id" match="map/entry" use="@key"/>
    
        <xsl:function name="mf:evaluate" as="node()?">
            <xsl:param name="path" as="xs:string"/>
            <xsl:param name="context" as="node()"/>
            <xsl:evaluate xpath="$path" context-item="$context"></xsl:evaluate>
        </xsl:function>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* , node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="node()[key('node-by-id', generate-id(), $mapped-nodes)]">
            <xsl:comment select="key('node-by-id', generate-id(), $mapped-nodes)"/>
            <xsl:text>&#10;</xsl:text>
            <xsl:copy>
                <xsl:apply-templates select="@* , node()"/>
            </xsl:copy>
        </xsl:template>
    
    
    </xsl:stylesheet>
    
    
    
    
    
    以下是最初发布的代码的编辑版本,它使用XSLT 3.0映射功能而不是临时文档来存储动态XPath求值找到的节点的生成id与注释之间的关联:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:math="http://www.w3.org/2005/xpath-functions/math"
        xmlns:map="http://www.w3.org/2005/xpath-functions/map"
        xmlns:mf="http://example.com/mf"
        exclude-result-prefixes="xs math map mf"
        version="3.0">
    
        <xsl:param name="paths-url" as="xs:string" select="'paths1.xml'"/>
        <xsl:param name="paths-doc" as="document-node()" select="doc($paths-url)"/>
    
        <xsl:output indent="yes"/>
    
        <xsl:variable 
            name="mapped-nodes"
            as="map(xs:string, xs:string)"
            select="map:new(for $path in $paths-doc/paths/xpath, $node in mf:evaluate($path/@location, /) return map:entry(generate-id($node), string($path/@annotate)))"/>
    
        <xsl:function name="mf:evaluate" as="node()?">
            <xsl:param name="path" as="xs:string"/>
            <xsl:param name="context" as="node()"/>
            <xsl:evaluate xpath="$path" context-item="$context"></xsl:evaluate>
        </xsl:function>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* , node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="node()[map:contains($mapped-nodes, generate-id())]">
            <xsl:comment select="$mapped-nodes(generate-id())"/>
            <xsl:text>&#10;</xsl:text>
            <xsl:copy>
                <xsl:apply-templates select="@* , node()"/>
            </xsl:copy>
        </xsl:template>
    
    
    </xsl:stylesheet>
    
    
    
    
    

    作为第一个样式表,它需要运行Saxon9.5PE或EE

    “接得好,”马丁霍宁说。当我编辑我的答案以展示一个更健壮的匹配示例时,我忽略了更新输入XML。现在修好了。谢谢。我想这可能是我将采用的方法,因为我现在对3.0一点都不熟悉。我尝试过使用
    saxon:evaluate
    函数,我怀疑它与Martin的解决方案大致相同。关于这个解决方案,我还没有找到一种方法来注释作为属性节点的XPath。e、 g.
    “/root/c/@x”
    。这是一个非常不同但很好的解决方案+谢谢,丹尼尔,这或多或少是我想到的。我想接下来的问题与
    xsl:if
    元素中
    test
    谓词的性能有关。它是否可能是除
    O(n)
    以外的任何东西,其中
    n
    是路径数?我对这个问题没有很好的把握。关于这个解决方案,我想到了另一件事。我相信如果你的
    path.xml
    有奇怪的XPath,它会失败。因为