我有一个像这样的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]"/>
但显然这不起作用。
答案 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所提到的,这还包括仅匹配字符串部分的属性,如it
,auth
,sb
,pub
等,所以这只是意义如果知道这些案件不存在。
在XSLT 2.0中,我首选的解决方案是:
<xsl:variable name="attrNames" select="'title','author','isbn','publisher'"/>
<xsl:template match="/ns:Library/ns:Book/@*[name() = $attrNames]"/>