【问题标题】:XSLT copy with modifications带有修改的 XSLT 副本
【发布时间】:2011-03-27 01:24:49
【问题描述】:

我一直在尝试在这些限制范围内工作,我使用的是 XSLT 1.0 {under .net}。 我希望能够做到以下几点: 我是 xsl:for-each'ing 通过一组类型的节点

   <node>
     <data> unknown unstructured xml </data>
     <owner></owner>
   </node>

我希望能够输出

   <node>
     <data> unknown unstructured xml </data>
     <!--RESULT of calling an XSL template with certain parameters -->
   </node>

到目前为止,我认为我可以在here 中执行类似的操作:

    <xsl:copy> 
        <xsl:apply-template name="findownerdetails">
           <xsl:with-param name="data" select="something" />
        </xsl:apply-template> 
    </xsl:copy> 

但这显然是无效的。有什么建议可以让这个工作或实现类似的东西吗?恐怕我不能只调用应用模板,因为我想要的模板将取决于我通过节点元素列表构建的一些数据。

任何建议表示赞赏

【问题讨论】:

  • 好问题 (+1)。请参阅我的回答,了解完全符合 XSLT 精神的最简单解决方案,利用最基本的 XSLT 设计模式——使用和覆盖标识规则。

标签: xml xslt .net-3.5 mxml


【解决方案1】:
<xsl:template match="node">
  <node>
    <xsl:copy-of select="data"/>
    <!-- assuming this next bit in your question example
    is something you are happy with -->
    <xsl:call-template name="findownerdetails">
      <xsl:with-param name="data" select="something" />
    </xsl:call-template> 
  </node>
</xsl:template>

【讨论】:

  • 谢谢,我希望不久前我能想到这样做。供参考:如果节点元素有许多我需要复制的未知属性会发生什么?还有可能做一个
  • 您可以执行 来回答您的两个问题。对于更复杂的情况,或者来自不同名称空间的“所有者”元素的可能性,那么身份覆盖(如在 Dimitre 的回答中)变得更加优雅(我们可以通过 Dimitre 和我的回答扩展以处理更复杂的情况;我的在一定程度的复杂性之下更简洁,而 Dimitre 则高于它,这也是 Dimitre 更通用的原因,每个 XSLT 编码人员都应该知道)。 (ps,如果以上有帮助,接受答案会很好)。
  • 感谢乔恩提供的额外信息,看起来它可以解决问题。由于 Dimitre 的答案不处理传递参数而你的,我会接受你的答案 - 谢谢 :)
  • @GreyCloud:您关于“Dimitre 的答案不处理传递参数”的说法是不正确的——您根本没有要求这样做,您的问题也不需要传递参数。我已经更新了解释这些要点的答案。这是您学习基础知识和非常有帮助的好时机。
  • @Jon Hanna:你的答案是错误的。 apply-templates 指令中没有 @name。这是call-template 指令,其中有@name
【解决方案2】:

这是一个典型的问题示例,使用和覆盖 identity rule 可以得到最好的解决:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

 <xsl:template match="owner">
    <owner-details>
      <xsl:value-of select="."/>
    </owner-details>
 </xsl:template>
</xsl:stylesheet>

在此 XML 文档上应用此转换时(基于提供的带有附加属性和所有者详细信息的 XML 文档):

<node attr1="x" attr2="y">
    <data> unknown unstructured xml </data>
    <owner>
        <details>
            <name>John Smith </name>
            <profession>XSLT programmer</profession>
        </details>
    </owner>
</node>

产生想要的结果

<node attr1="x" attr2="y">
   <data> unknown unstructured xml </data>
   <owner-details>John Smith XSLT programmer</owner-details>
</node>

请注意

  1. 身份模板以递归方式“按原样”复制文档中的每个节点

  2. 我们只覆盖我们希望以其他方式处理的元素的标识模板。任何匹配模式比标识模板更具体的模板都会覆盖它——XSLT 处理器总是为节点选择最具体的匹配模板。

  3. 使用和覆盖标识规则是最基本的、最强大、最通用的和最优雅的 XSLT 设计模式。它专门用于几乎所有 XSLT 转换:用于删除/重命名/修改/添加特定节点并保持所有其他节点不变。

  4. OP 在评论中建议此解决方案不允许传递参数。这不是真的。任何模板(包括身份规则)都可以编写为具有参数——当需要时。在这种特殊情况下,不需要通过模板传递参数。

  5. owner匹配的模板不需要调用另一个模板 -- 这里可以完成所有所有者特定的处理。

【讨论】:

  • 嗨 Dimitre,谢谢您的解决方案,我在另一个线程中看到了类似的答案,但恐怕它不起作用,因为我无法通过 调用。
  • @GreyCloud:你不明白:1.你可以通过任何模板传递参数。对于您问题中的问题,这不是必需的。修改问题,使其需要传递参数,我将向您展示如何。 2. 在与owner 匹配的模板中,您无需调用另一个模板并将参数传递给它——您只需处理此模板中的owner 元素(及其子树)——而这这就是我的回答所暗示的。
  • 如何通过“”传递参数?
  • @GreyCloud: &lt;xsl:apply-templates select="node()|@*"&gt;&lt;xsl:with-param name="paramName" select="whateverNecessary"/&gt;&lt;/xsl:apply-templates&gt;
  • @Dimitre:+1 以获得完整和正确的答案。此外,当您回答这个简单的问题时,您似乎还没有听过(我关注了 OP 链接)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多