2016-09-07 100 views
0

我想这样做如何使用包含图案的XSLT变量在模板匹配表达式

<xsl:variable name="myPattern" select="node1|node2"/> 
<xsl:template match="$myPattern"> 
    ... 
</xsl:template> 
<xsl:template match="/"> 
    ... 
    <xsl:for-each select="distinct-values(//$myPattern/name/text()"> 
     ... 
    </xsl:for-each> 
</xsl:template> 

我用XSLT版本2.0和3.0无济于事尝试这样做。任何提示?

原因:该模式有点复杂,我想在几个地方使用它,而不仅仅是这场比赛。

编辑:

我解决我的问题,现在通过接受一个事实,即该变量不包含字符串/模式,但结果节点。如果我将其修改为

<xsl:variable name="myNodes" select="//(node1|node2)"/> 
<xsl:template match="$myNodes"> 
    ... 
</xsl:template> 
<xsl:template match="/"> 
    ... 
    <xsl:for-each select="distinct-values($myNodes/name/text()"> 
     ... 
    </xsl:for-each> 
</xsl:template> 

它工作正常。

我仍然想知道为什么不能简单地将字符串存储在变量中,并在允许字符串的任何位置使用它。

+1

XSLT 3.0允许您使用例如'match =“$ xyz”'并解释“$ xyz匹配变量$ xyz的值中存在的任何节点”。因此,您需要向我们展示一个最小但完整的XML,XSLT样本,您期望的输出,输出或错误,以及有关使用的XSLT处理器的信息,以便我们能够分辨出哪些是错误的。显然,我希望你的变量声明看起来像例如'',除非你正在寻找的元素真的是根元素。 –

+0

@MartinHonnen:你说得对。我希望在短时间内让其他人在搜索答案时节省时间。我认为你的评论比你的回答更好,因为这是我解决它的方法:''。 – mdr

+0

@mdr您将不得不使用某种'evaluate()'函数将字符串转换为XPath表达式(如果这就是您的意思)。 –

回答

2

至于文本替换,使用XSLT 3.0,您可以使用使用静态参数有一个字符串值,然后所谓的阴影属性(https://www.w3.org/TR/xslt-30/#shadow-attributes):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math" 
    version="3.0"> 

    <xsl:param name="myPattern" static="yes" as="xs:string" select="'node1|node2'"/> 

    <xsl:template _match="{$myPattern}"> 
     <matched name="{node-name()}"> 
      <xsl:apply-templates/> 
     </matched> 
    </xsl:template> 

    <xsl:template match="/*"> 
     <xsl:copy> 
      <xsl:for-each _select="distinct-values(//{$myPattern}/text())"> 
       <value> 
        <xsl:value-of select="."/> 
       </value> 
      </xsl:for-each> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

这转变

<root> 
    <node1>a</node1> 
    <node2>1</node2> 
    <node1>a</node1> 
</root> 

into

<root><value>a</value><value>1</value> 
     <matched name="node1">a</matched> 
     <matched name="node2">1</matched> 
     <matched name="node1">a</matched> 
</root> 

在XSLT 3.0 y您可以使用模板的match模式的变量或参数引用,但它不是发生的文本替换,而是“$ xyz匹配变量$ xyz的值中存在的任何节点”(https://www.w3.org/TR/xslt-30/#pattern-examples)。

于是用XSLT是

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:param name="delete" select="//*[contains-token(@class, 'foo')]"/> 

    <xsl:mode on-no-match="shallow-copy"/> 

    <xsl:template match="$delete"/> 

</xsl:stylesheet> 

和XML输入是

<html> 
    <head> 
     <title>test</title> 
    </head> 
    <body> 
     <p class="foobar bar">Paragraph 1.</p> 
     <p class="foo bar">Paragraph 2.</p> 
     <p class="bar">Paragraph 3.</p> 
     <p class="foo">Paragraph 4.</p> 
    </body> 
</html> 

相符的XSLT 3.0处理器等撒克逊9.7 EE输出

<html> 
    <head> 
     <title>test</title> 
    </head> 
    <body> 
     <p class="foobar bar">Paragraph 1.</p> 

     <p class="bar">Paragraph 3.</p> 

    </body> 
</html> 
2

我建议使用一个功能而不是变量:

<xsl:function name="_:myPattern" as="xs:boolean"> 
    <xsl:param name="node" as="node()"/> 
    <xsl:sequence select="self::node1() | self::node2()"/> 
</xsl:function> 

<xsl:template match="node()[_:myPattern(.)]"> 
... 
</xsl:template> 
+0

这似乎是做我的意图:评估模式,无论使用变量(或更确切地说,功能)。但是:哇!它不是偶尔为XSLT用户/程序员调用的简单维护工具。所以我会坚持更简单的(见我的编辑)。但我确实学到了很多东西。 – mdr

+0

谢谢。我无法得到这个工作,不知道它是否是一个错字?我试过存在($节点/(self :: node1 | self :: node2))似乎工作。或者,可能带有'element()?'的$ node /(self :: node1 | self :: node2)作为返回类型。 – dave

+1

如果没有将整个线程重新分页回到我的大脑中,我怀疑我打算使用'' –