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

时间:2015-01-07 22:04:43

标签: xml templates xslt removing-whitespace apply-templates

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

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

<xsl:template match="/">

做转型工作......

跳转到匹配=&#34; node()&#34;模板

</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从源代码复制,转换为大写并删除了空格。 注2 / Point.1删除了空格。 注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>

1 个答案:

答案 0 :(得分:1)

这不是一个真正的答案,但是评论的时间太长了。

如果将两个不同的模板(使用模式)应用于相同的节点,最终将得到两个结果节点。我不认为这是你想要的,所以你需要做两个中的一个:

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

(b)将两个转换合并为一个:遗憾的是,您没有向我们展示第一次转换的模板(这就是为什么这不是一个答案),但作为一个例子,如果你想转移一个节点&# 39; s文本大写修剪空白,你可以做到:

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

如果规范化空白是你应该做的第二次转换,那么我相信选项(b)将是更好的选择。