如何将两个模板应用于同一组节点,特别是 XML 中的所有节点

How to apply two templates to the same set of nodes, specifically all the nodes in a XML

我试图从输入 XML 文件创建输出 XML 文件。一些节点需要从输入复制到输出,一些被省略,一些节点将以某种方式修改它们的文本。但是除此之外,我还需要 trim 每个节点文本中的空格。我假设执行此操作的最佳方法是使用模式或其他一些属性在同一组节点上调用两个模板,但我无法弄清楚如何执行此操作。节点太多,无法手动将 trim() 应用于每个节点。

删除空格的代码本身有效(来自另一个 Whosebug 的解决方案),但我不知道如何使用另一个模板修改 XML 然后应用这两个模板。我希望解决方案类似于:

<xsl:template match="/">

做改造工作...

跳转到匹配="node()"模板

</xsl:template>

去除空白解决方案:

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

<xsl:template match="text()">
    <xsl:value-of select="normalize-space(.)" />
</xsl:template>

这是一个示例输入:

<ABC Id="64" Author="FirstName">
    <Note Type="Test" ID="01">
        <Note.1>string     </Note.1>
        <Note.2>
            <Point.1>string2        </Point.1>
            <Point.2>hello</Point.2>
        </Note.2>
    </Note>
</ABC>

预期输出:

<ABC Id="64" Author="FirstName">
   <Note Type="Test" ID="01">
      <Note.1>STRING</Note.1> 
      <Note.2>
         <Point.1>string2</Point.1>
      </Note.2>
    </Note>
</ABC>

Note.1 是从源代码复制而来的,转换为大写并删除了空格。 Note.2/Point.1 删除了空格。 Note.2/Point.2不是从源码复制过来的

编辑 --- 我当前的代码。它正确地删除了空格。但是,结果 XML 包含源中删除了空格的每个节点,而不仅仅是在第一个转换中复制的那些节点。我将这些节点存储在一个变量中,然后将该变量传递到我的删除空白模板中。关于为什么去除空格的模板作用于原始集而不是变量中包含的集,有什么想法吗?

  <xsl:template match="/">
    <!--Store the results in a variable called transformation_result-->
    <xsl:variable name="transformation_result">
      <!--Go to the normal transformation template -->
      <xsl:call-template name="transformation"/>
    <!--Results now in $transformation_result -->
    </xsl:variable>    
    <!-- If you want to see what is in the variable -->
    <!--<xsl:copy-of select="$transformation_result"/>-->
    <!-- Go to the template that copies all input -->
    <xsl:call-template name="copy_for_whitespace">
      <!-- The $tranformation_result is the parameter passed in by the name of: input -->
      <xsl:with-param name="input" select="$transformation_result"/>
    </xsl:call-template>
  </xsl:template>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
  <xsl:template name="transformation">
    <imp1:HIJ>
      <xsl:copy-of select="/imp1:HIJ/imp1:ABC">
        <?oracle-xsl-mapper-position imp1:ABC?>
      </xsl:copy-of>
    </imp1:HIJ>
  </xsl:template>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
  <xsl:template name="copy_for_whitespace" match="node()">          
    <xsl:param name="input"/>
    <xsl:variable name="test">
    <xsl:copy>                                                 
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
        </xsl:variable>
    <xsl:copy-of select="$test"/>
  </xsl:template>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
  <xsl:template match="text()">                                     
    <xsl:value-of select="normalize-space()"/>
  </xsl:template>

这不是一个真正的答案,但对于评论来说太长了。

如果将两个不同的模板(使用模式)应用于相同的 节点,您最终将得到两个结果节点。我认为这不是您想要的,因此您需要执行以下两项操作之一:

(a) 分两次进行转换:将第一组模板应用于源文档中的原始节点,同时将结果传递给变量;然后将第二组模板应用于变量中的(新)节点,这次将结果引导至输出。

(b) 将两个转换合并为一个:不幸的是,您没有向我们展示第一个转换的模板(这就是为什么这不是一个答案),但是作为一个例子,如果您想要转换一个节点的文本大写 trim 空白,你​​可以简单地做:

<xsl:template match="Note.1">
    <xsl:copy>
        <xsl:value-of select="normalize-space(upper-case(.))"/>
    </xsl:copy>
</xsl:template>

如果您的第二次转换只需要规范化空白,那么我相信选项 (b) 会是更好的选择。