匹配 XSLT 上的属性而不是匹配整个元素

Match attribute on XSLT instead of matching the whole element

我想编写一个匹配属性而不是节点的 XSL 模板,

我认为有这样的东西:

<xsl:template match="@href | @conref | @conrefend">
    <xsl:message select="."/>
</xsl:template>

将匹配这 3 个属性名称中的任何一个并打印以控制属性的值,因为范围是属性本身而不是节点。

但我的测试证明我错了,我只能匹配包含任何这些属性的节点,如下所示:

 <xsl:template match="*[@href or @conref or @conrefend]">
   <xsl:message select="if(not(@href)) 
                        then    
                          if(not(@conref)) 
                          then @conrefend 
                          else @conref 
                        else @href"/>  
   </xsl:template>

这种方法的问题在于,如果碰巧存在一个节点具有多个属性,那么只有一个被处理,我需要处理所有这些属性。

关于第一种方法为何不起作用的任何想法?

编辑1: 完整的 xslt:

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

     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>             
     <xsl:template match="@conref|@conrefend|@href">
        <xsl:message select="."/>
     </xsl:template>
   </xsl:stylesheet>

测试XML:

  <links>
      <image conref="COPY-GUID/*+-862416}39-37CD-4CF7-A7AA-F09F4A763944" />
   </links>

现在 XSLT 没有匹配任何东西。

您确实可以像第一个模板那样匹配模板中的属性。一定是其他地方出了问题...

看看恒等变换:

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

它可以很好地匹配您正在做的备选方案,其中一个备选方案适用于所有属性 (@*)。

现在考虑 xsl:apply-templates 语句。请注意 @* 是如何显式调用的。你确定你给你的模板一个机会来应用属性吗?如果你打电话,xsl:apply-templates 像这样,例如:

        <xsl:apply-templates select="*"/>

意识到只会选择元素,而不是属性。另请注意,node() 也不包含属性。

更新

没错。您的属性匹配模板永远没有机会应用。

添加上面的标识模板,或类似这样的内容:

<xsl:template match="/">
    <xsl:apply-templates select="//@*"/>
</xsl:template>

让您的属性匹配模板有机会应用。

默认情况下,XSLT 不查找匹配属性节点的模板。将模板显式应用于输入中的所有属性 XML.

顺便问一下,您确定要使用 xsl:message 吗? xsl:message 的内容不包含在转换输出中。你是说 xsl:value-of 吗?另外,如果你输出的是文本,你应该声明输出方法是文本。

样式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:apply-templates select="//@*"/>
    </xsl:template>

    <xsl:template match="@conref">
        <xsl:value-of select="."/>
    </xsl:template>

</xsl:stylesheet>

文本输出

COPY-GUID/*+-862416}39-37CD-4CF7-A7AA-F09F4A763944

实际上,在这种非常简单的情况下,第一个模板就足以获得相同的输出:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:apply-templates select="//@*"/>
    </xsl:template>

</xsl:stylesheet>

这是因为,一旦将模板应用于属性节点,就会有一个默认输出其字符串值的内置模板。

您当前方法的问题在于从未应用与 attribute/s 匹配的模板。它不被应用,因为内置模板规则仅匹配根节点和元素节点,并且它仅将模板应用于子节点 nodes。要将模板应用于属性,您必须自己明确地应用它。

http://www.w3.org/TR/xslt20/#built-in-rule