如何将两个模板应用于同一组节点,特别是XML中的所有节点 [英] How to apply two templates to the same set of nodes, specifically all the nodes in a XML

查看:90
本文介绍了如何将两个模板应用于同一组节点,特别是XML中的所有节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I trying to create an output XML file from an input XML file. Some of the nodes need to be copied from input to output, some with be omitted, and a few of the nodes will have their text modified in some way. However in addition to this, I need to trim the whitespace from the text of every node. I assume that the best way to do this is to have two templates called on the same set of nodes using a mode or some other attribute, but I cannot figure out how to do this. There are too many nodes to manually apply a trim() to every node.

删除空白的代码本身是有效的(另一个Stackoverflow的解决方案),但是我不知道如何使用另一个模板修改XML,然后应用这两个模板.我希望解决方案是这样的:

The code to remove the whitespace works by itself (solution from another Stackoverflow), but I do not know how to modify the XML using another template and then apply these two templates. I expect the solution to be something like:

<xsl:template match="/">

做改造工作...

跳转到match ="node()"模板

jump to match="node()" template

</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.

Note.1 was copied from source, transformed to uppercase and had whitespace removed. Note.2/Point.1 had whitespace removed. Note.2/Point.2 was not copied from the source.

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

Edit --- My current code. It properly removes the whitespace. However the resulting XML contains every node from the source with the whitespace removed, instead of only those nodes copied in the first transformation. I am storing these nodes in a variable and then passing that variable into my remove whitespace template. Any thoughts on why the whitespace-removing template is acting on the original set instead of the set contained in the variable?

  <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>

推荐答案

这并不是真正的答案,但是评论太久了.

This is not really an answer, but it's too long for a comment.

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

If you apply two different templates (using modes) to the same node, you will end up with two resulting nodes. I don't think that's what you want, so you need to do one of the two:

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

(a) Do the transformation in two passes: apply the first set of templates to the original nodes in the source document, while channeling the result to a variable; then apply the second set of templates to (new) nodes in the variable, this time channeling the result to the output.

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

(b) Merge the two transformations into one: unfortunately, you did not show us the templates for the first transformation (which is why this cannot be an answer), but as an example, if you want to shift a node's text to uppercase and trim the whitespace, you can do simply:

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

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

If normalizing whitespace is all your second transformation is supposed to do, then I believe option (b) would be the better choice.

这篇关于如何将两个模板应用于同一组节点,特别是XML中的所有节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆