是否有更短的方式来编写此XSLT匹配?

时间:2014-03-13 09:35:34

标签: xml xslt xslt-1.0 libxml2

我有一个像这样的XSLT 1.0匹配:

<xsl:template match="/ns:Library/ns:Book/@title | /ns:Library/ns:Book/@author | /ns:Library/ns:Book/@isbn | /ns:Library/ns:Book/@publisher"/>

有没有更短的方式来写这个?

我希望有类似的东西:

<xsl:template match="/ns:Library/ns:Book/@*[title|author|isbn|publisher]"/>

但显然这不起作用。

4 个答案:

答案 0 :(得分:2)

撰写您尝试过的内容的正确方法是:

<xsl:template match="/ns:Library/ns:Book/@*[name() = 'title' or name() = 'author' or name() = 'isbn' or name() = 'publisher']"/>

当然不是很短。但是还有其他方法可以编写更简洁的代码:

1为元素和属性匹配单独的模板匹配

为避免过长的表达式,您可以将代码拆分为单独的模板。在第一个模板中,匹配元素:

<xsl:template match="/ns:Library/ns:Book">
   <xsl:copy>
     <xsl:apply-templates select="@*"/>
   </xsl:copy>
</xsl:template>

然后,写一个属性模板:

<xsl:template match="@title|@author|@isbn|@publisher">
   <!--Process attributes-->
</xsl:template>

2指定匹配的属性

<xsl:template match="/ns:Library/ns:Book/@*[name() != 'date']"/>

最终,它取决于您的输入XML数据和XSLT上下文是否有意义。例如,如果有100个您不想匹配的属性,那么第二个想法就无济于事。

您的主要关注点应该是准确性(产生正确的输出XML),其次是代码的可读性。如果对XSLT代码的更改没有改进其中任何一个,那么根本不可能改变样式表。

答案 1 :(得分:1)

XSLT非常受上下文驱动。在没有看到如何(从哪个上下文)应用此模板的情况下(并且没有看到XML和样式表的其余部分),任何答案都是一个猜测。从技术上讲,你可以写:

<xsl:template match="@title|@author|@isbn|@publisher"/>

并从/ns:Library/ns:Book的上下文中应用此模板。


请记住,XSLT自然是冗长的,简洁性很少是首要任务。

答案 2 :(得分:0)

在XSLT 3.0中,您可以编写

match="/ns:Library/ns:Book/(@title | @author)"

在1.0中,可能的选项是

match="/ns:Library/ns:Book/@*[name()='author' or name()='title']"

但我更喜欢冗长的原创。至少在撒克逊语中(我不能代表其他处理器),匹配显式名称的模式总是比匹配通配符(*或@ *)并依赖于谓词的模式快得多。

您确定需要"/ns:Library/ns:Book/"部分吗?您确定match="@title|@author"无法完成这项工作吗?

答案 3 :(得分:0)

为了缩短XSLT 1.0,我经常写一些类似的东西:

<xsl:template match="/ns:Library/ns:Book/@*[contains('title|author|isbn|publisher',name())]"/>

或使用全局变量:

<xsl:variable name="attrNames">title|author|isbn|publisher</xsl:variable>

<xsl:template match="/ns:Library/ns:Book/@*[contains($attrNames,name())]"/>

修改

正如@nwellnhof所提到的,这还包括仅匹配字符串部分的属性,如itauthsbpub等,所以这只是意义如果知道这些案件不存在。


在XSLT 2.0中,我首选的解决方案是:

<xsl:variable name="attrNames" select="'title','author','isbn','publisher'"/>

<xsl:template match="/ns:Library/ns:Book/@*[name() = $attrNames]"/>