XSLT键值和apply-template

时间:2014-01-14 10:42:50

标签: xslt xslt-2.0

关键值和apply-template的XSLT 2.0处理问题。

来源xml

<?xml version="1.0" encoding="UTF-8"?>
<ELEMENTS>
  <EA-NUMERICAL ID="MyFloat_20_62045">
        <NAME>MyFloat</NAME>
  </EA-NUMERICAL>
  <RANGEABLE-VALUE-TYPE ID="PercentType_20_62177">
        <NAME>PercentType</NAME>
        <BASE-RANGEABLE-REF TYPE="EA-NUMERICAL">/MyFloat_20_62045</BASE-RANGEABLE-REF>
  </RANGEABLE-VALUE-TYPE>
  <RANGEABLE-VALUE-TYPE ID="TorqueType_20_62239">
        <NAME>TorqueType</NAME>
        <BASE-RANGEABLE-REF TYPE="EA-NUMERICAL">/MyFloat_20_62045</BASE-RANGEABLE-REF>
  </RANGEABLE-VALUE-TYPE>
</ELEMENTS>

XSLT报告RANGEABLE-VALUE-TYPE的关键定义:

<xsl:key name="by-rangeable-value-type" match="RANGEABLE-VALUE-TYPE" use="BASE-RANGEABLE-REF"/>
<xsl:key name="ea-numerical-type" match="EA-NUMERICAL" use="@ID"/>

然后我有两个模板(第一个用于完整信息,另一个用于之前报告EA-NUMERICAL的情况):

<!-- Reporting the full information -->
<xsl:template match="RANGEABLE-VALUE-TYPE[. is key('by-rangeable-value-type', BASE-RANGEABLE-REF)[1]]">
</xsl:template>

<!-- Reporting the reference -->
<xsl:template match="RANGEABLE-VALUE-TYPE[not(. is key('by-rangeable-value-type', BASE-RANGEABLE-REF)[1])]">
<object>
   <xsl:attribute name="href">#<xsl:value-of select="tokenize(BASE-RANGEABLE-REF, '/')[last()]"/></xsl:attribute>
</object>
</xsl:template>

模板通话:

<xsl:apply-templates select="key('ea-numerical-type', tokenize(BASE-RANGEABLE-REF, '/')[last()])"/>

问题是EA-NUMERICAL是否在其他模板的其他地方/早些时候报告过。

现在,在第一次RANGEABLE-VALUE-TYPE处理期间,它将再次完全报告(通过使用第一个模板,如键定义状态)。对于第二个RANGEABLE-VALUE-TYPE,它正确使用参考模板。

但是XSLT 2.0中是否有一种方法可以创建/组合具有多个不同元素或属性值的键? (在此标记化BASE-RANGEABLE-REF值和EA-NUMERICAL id属性值的示例组合中?)

1 个答案:

答案 0 :(得分:2)

您可以使用

更改密钥定义以包含两者
<xsl:key name="by-rangeable-value-type"
         match="RANGEABLE-VALUE-TYPE/BASE-RANGEABLE_REF | EA-NUMERICAL/@ID"
         use="tokenize(., '/')[last()]"/>

现在,给定ID的密钥集将是ID属性节点和BASE-RANGEABLE-REF元素节点的混合。要检查给定的RANGEABLE-VALUE-TYPE是否是第一次提及,您可以使用类似

的内容
<xsl:template match="RANGEABLE-VALUE-TYPE[BASE-RANGEABLE-REF intersect
  key('by-rangeable-value-type', tokenize(BASE-RANGEABLE-REF, '/')[last()])[1]]">

如果这是第一个匹配的BASE-RANGEABLE-REF 并且之前没有EA-NUMERICAL,它将匹配。

然后,您还需要两种模式来报告完整信息&#34;模板,因此您可以将EA-NUMERICAL映射到交叉引用(如果已经完整报告了RANGEABLE-VALUE-TYPE

<xsl:template match="EA-NUMERICAL" mode="copy" name="copy-ean">
  <!-- whatever you do to report the full details -->
</xsl:template>

<!-- first mention (i.e. not yet mentioned in any RANGEABLE-VALUE-TYPE) -->
<xsl:template match="EA-NUMERICAL[@ID is key('by-rangeable-value-type', @ID)[1]]">
  <xsl:call-template name="copy-ean" />
</xsl:template>

<!-- other mentions becom href -->
<xsl:template match="EA-NUMERICAL">
  <object href="#{@ID}" />
</xsl:template>

并在您的&#34;首先RANGEABLE-VALUE-TYPE&#34;模板使用

<xsl:apply-templates mode="copy" select="key('ea-numerical-type', tokenize(BASE-RANGEABLE-REF, '/')[last()])"/>