有没有办法在 XSLT 转换中用应用模板替换 for-each?

Posted

技术标签:

【中文标题】有没有办法在 XSLT 转换中用应用模板替换 for-each?【英文标题】:Is there a way to replace the for-each with apply-templates in an XSLT Transform? 【发布时间】:2018-02-23 15:05:32 【问题描述】:

环境: XSLT 1.0 转换将获取partOne 部分中的每个元素,并使用partTwo 属性在partTwo 部分中查找@field 属性,然后输出@value 属性。

我正在使用for-each 循环,想知道apply-templates 是否可以工作?

xml

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="file.xslt"?>

<xml>
  <partOne>
    <target field="hello"/>
    <target field="world"/>
  </partOne>
  <partTwo>
    <number input="2" find="hello" value="valone" />
    <number input="2" find="world" value="valtwo"  />
    <number input="2" find="hello" value="valthree"  />
    <number input="2" find="world" value="valfour"  />    
  </partTwo>
</xml>

xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="/xml/partOne/target">
    ,<xsl:value-of select="@field"/>

    <xsl:for-each select="/xml/partTwo/number[@find=current()/@field]">
      ,<xsl:value-of select="@value"/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

输出:

,hello
  ,valone
  ,valthree

,world
  ,valtwo
  ,valfour

【问题讨论】:

【参考方案1】:

嗯,改变似乎很简单

<xsl:for-each select="/xml/partTwo/number[@find=current()/@field]">
  ,<xsl:value-of select="@value"/>
</xsl:for-each>

<xsl:apply-templates select="/xml/partTwo/number[@find=current()/@field]"/>

有模板

<xsl:template match="partTwo/number">
      ,<xsl:value-of select="@value"/>
</xsl:template>

到目前为止,作为您的根模板处理您需要将其更改为的所有元素

  <xsl:template match="/">
    <xsl:apply-templates select="xml/partOne"/>
  </xsl:template>

避免两次处理 partTwo 元素。

对于交叉引用,您可能希望在两个版本中都使用一个键:

<xsl:key name="ref" match="partTwo/number" use="@find"/>

然后是select="key('ref', @field)",而不是select="/xml/partTwo/number[@find=current()/@field]" 用于apply-templatesfor-each

【讨论】:

我得到了想要的输出,然后一些...,valone,valtwo,valthree,valfour 也被输出了,那部分是不正确的。任何想法为什么这样做? @Rod,查看编辑,您当前的方法将处理 partTwo 两次,您需要更正匹配 / 的模板中的应用模板。 谢谢,成功了。但是,我认为apply-templatesselect 表达式必须与模板的match 表达式完全匹配? 选择表达式选择的节点必须匹配模板规则中的match 模式。例如select="*"选择的节点可以匹配match="para"的模板规则,而select="para"选择的节点可以匹配match="*"的规则。 @Rod,我添加了xsl:key/key 使用的示例。

以上是关于有没有办法在 XSLT 转换中用应用模板替换 for-each?的主要内容,如果未能解决你的问题,请参考以下文章

我的多页迭代 PDF 转换器应该使用啥 XSLT:FO 布局?

使用 XSLT 2.0 检查 <fo:page-number> 是不是为偶数

是否可以将 XSLT 转换应用于 DOM 元素?

如何使用 XSLT 替换命名空间中的元素?

有没有在bash中用波浪号替换主目录的好方法?

如何在java中读取xep文件数据