我该如何重构这个XSLT

时间:2014-08-29 08:29:13

标签: xml xslt refactoring

我有一个关于在我正在进行的项目上重构som XSLT代码的问题。我现在有XSLT

<pdf:sometext text="{$metadata/namespace:template 
                     /namespace:template_collection
                     //namespace:option
                     [namespace:identificator 
                      = $report_option_identifier]
                     /namespace:name}"/>

问题是需要扩展XSLT才能访问更多节点(原始XML的新版本,稍有更改的命名空间和略微更改的标记)。

我想出了这段代码:

<xsl:variable name="report_template_collection" 
              select="$metadata
                      /namespace:template
                      /namespace:template_collection 
                      | 
                      $metadata
                      /namespace2:templateV2
                      /namespace2:template_collectionV2" />
<xsl:variable name="current_report_option" 
              select="namespace:option | namespace2:optionV2" />
<xsl:variable name="incomplete_report_option_text" 
              select="$report_template_collection
                      //$current_report_option
                      [namespace:identificator 
                      = $report_option_identifier]
                      /namespace:name"/>

<pdf:sometext text="{$incomplete_report_option_text}"/>

但是在编译时会出现错误:

Unexpected token '$' in the expression. $report_template_collection// -->$<-- current_report_option[namespace:opt...

所以我的问题是:如何重构XSLT以考虑新的类型(名为V2)和另一个名称空间。重要的是,相同的XSLT符合所有版本的XML(旧版本和新版本)。

提前致谢!

2 个答案:

答案 0 :(得分:1)

A/B/$C形式的XPath表达式在XPath 2.0中实际上是合法的,但在XPath 1.0中则不然。但它可能并不意味着你认为它意味着什么。就像@ewh我怀疑(没有任何证据)你想象如果变量$C绑定到表达式D|E,那么A/B/$C是另一种写A/B/(D|E)的方式。情况并非如此; $C绑定到一个值(一系列节点),而不是一个表达式。

您可以使用函数而不是变量:

<xsl:function name="f:current_report_option">
  <xsl:param name="node" as="node()"/>
  <xsl:sequence select="$node/(D|E)"/>
</xsl:function>

<xsl:variable name="X" select="A/B/f:current_report_option(.)"/>

答案 1 :(得分:0)

您无法在xpath表达式中引用$current_report_option。您不能使用宏等XSLT变量,这是您尝试执行的操作。 $current_report_option的类型是节点集。

如果我正确地解释您的意图(错误地)$current_report_option,您应该执行以下操作:

<xsl:variable name="incomplete_report_option_text" 
              select="$report_template_collection
                      //*[self::namespace:option or
                          self::namespace2:optionV2]
                      [namespace:identificator 
                      = $report_option_identifier]
                      /namespace:name"/>

我将$current_report_option的用法替换为节点测试,以检查旧的或新的选项节点类型。