2014-03-13 49 views
0

我有一个XSLT 1.0的比赛是这样的:有没有更简单的方法来编写这个XSLT匹配?

<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]"/> 

但显然不起作用。

回答

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代码的更改不能改善其中的任何一种,那么更改样式表可能是一个坏主意。

+0

@nwellnhof你是对的 - 感谢纠正。 –

1

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

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

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


请记住,XSLT自然是冗长的,简洁性很少成为最优先考虑的事情。

+0

+1,比赛结束时有一个多余的']'。干杯! –

+0

@MathiasMüller谢谢! –

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"不会做这份工作吗?

+0

我确实需要上下文,因为有问题的属性出现在原始XML文件中,但我需要将“覆盖”应用于单个节点。 (这是一个基于更复杂的例子) – nielsbot

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,authsbpub等等,所以这只有在这些情况已知不存在时才有意义。


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

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

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

这将包括'it','auth','sb','pub'等属性。 – nwellnhof

+0

@nwellnhof当然,你必须知道你的xml结构,以确保其中没有其他属性。 –

相关问题