【问题标题】:How to apply two templates to the same set of nodes, specifically all the nodes in a XML如何将两个模板应用于同一组节点,特别是 XML 中的所有节点
【发布时间】:2015-01-10 01:06:17
【问题描述】:

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

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

<xsl:template match="/">

做转换工作...

跳转到 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>

【问题讨论】:

  • 如果您可以发布示例输入和预期输出,将有助于我们了解您想要实现的目标。
  • 我已经更新了帖子。希望输入、输出和改写有所帮助。
  • 您的“当前代码”似乎与问题无关。

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


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 谢谢!这对我有点帮助。我需要做你的建议而不是 b,因为有太多的节点来单独应用这个函数。
  • 我不太确定。
猜你喜欢
  • 2020-05-28
  • 2015-09-13
  • 1970-01-01
  • 2020-06-27
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 2021-12-24
相关资源
最近更新 更多