如何使用XSL检查XML文件中是否存在属性

33
在运行时,我可能会有两种XML文件格式:

  1. <root>
        <diagram> 
            <graph color= "#ff00ff">    
                <xaxis>1 2 3 12 312 3123 1231 23 </xaxis>
                <yaxis>1 2 3 12 312 3123 1231 23 </yaxis>
            </graph>  
        </diagram> 
    </root>
    
  2. <root>
        <diagram> 
            <graph>    
                <xaxis>1 2 3 12 312 3123 1231 23 </xaxis>
                <yaxis>1 2 3 12 312 3123 1231 23 </yaxis>
            </graph>  
        </diagram> 
    </root>
    
    根据颜色属性的存在,我需要处理x轴和y轴的值。我需要使用XSL完成这个操作。有人能帮助我提供一个片段,提示我如何检查这些条件吗?我尝试了使用。
    <xsl: when test="graph[1]/@color">
         //some processing here using graph[1]/@color values
    </xsl:when>
    

    我遇到了一个错误...


你是否使用了 xsl:choose 指令?(xsl:when+|xsl:otherwise) - user357812
是的,我徒劳地使用了xsl:choose ... xsl:when + xsl:otherwise条件。 - srivatsa
什么是上下文节点?/ 文档根节点,root 元素,diagram 元素,graph 元素...? - user357812
好问题,+1。请看我的答案,它使用了 XSLT 模式匹配和推送式处理等强大功能的最大化解决方案。 :) - Dimitre Novatchev
4个回答

37

这里有一种非常简单的条件处理方式,它利用了XSLT模式匹配的全部功能,采用了“推式”样式,并且避免了使用诸如<xsl:if><xsl:choose>等条件指令的需要:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/root/diagram[graph[1]/@color]">
  Graph[1] has color
 </xsl:template>

 <xsl:template match="/root/diagram[not(graph[1]/@color)]">
  Graph[1] has not color
 </xsl:template>
</xsl:stylesheet>

当对以下XML文档应用此转换时

<root>
    <diagram>
        <graph color= "#ff00ff">
            <xaxis>1 2 3 12 312 3123 1231 23 </xaxis>
            <yaxis>1 2 3 12 312 3123 1231 23 </yaxis>
        </graph>
        <graph>
            <xaxis>101 102 103 1012 10312 103123 101231 1023 </xaxis>
            <yaxis>101 102 103 1012 10312 103123 101231 1023 </yaxis>
        </graph>
    </diagram>
</root>

期望的、正确的结果已经生成:

  Graph[1] has color

当相同的转换被应用于此 XML 文档时

<root>
    <diagram>
        <graph>
            <xaxis>101 102 103 1012 10312 103123 101231 1023 </xaxis>
            <yaxis>101 102 103 1012 10312 103123 101231 1023 </yaxis>
        </graph>
        <graph color= "#ff00ff">
            <xaxis>1 2 3 12 312 3123 1231 23 </xaxis>
            <yaxis>1 2 3 12 312 3123 1231 23 </yaxis>
        </graph>
    </diagram>
</root>

再次得到期望和正确的结果:

  Graph[1] has not color

可以自定义此解决方案,并将所需的任何代码放入第一个模板中,必要时还可放入第二个模板中。


@Dimitre Novatchev 这个解决方案能否用于<apply-template>指令中?我正在使用XSLT从XML生成代码,并且我想过滤一些getter和setter。 - chepseskaf
@chepseskaf:如果你的意思是在xsl:apply-templatesselect属性中使用谓词,而不是在匹配模式中使用它们,那么答案是肯定的。但这样做并非必要,会导致更多的“推”或命令式处理方式,降低了简洁性、可理解性、可维护性和可优化性。 - Dimitre Novatchev
很遗憾看到这个有趣的问题虽然已经十年了,但没有被选中的答案。但我认为OP想要的是<xsl:template match="/root/diagram/graph[@color]"><xsl:template match="/root/diagram/graph[not(@color)]">,实际上处理所有图形节点。 - Fuujuhi
@Fuujuhi,也许你是对的,但在SO环境中,“所有的猜测都是平等的”。这里的OP没有透露他的目的——只是他在条件处理方面遇到了问题。这个答案展示了一个很好的解决方案,而不是试图深入猜测。 - Dimitre Novatchev

23

像这样在一个匹配中自定义模板

<xsl:template match="diagram/graph">
  <xsl:choose>
    <xsl:when test="@color">
         Do the Task
    </xsl:when>
    <xsl:otherwise>
         Do the Task
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>**

4
<xsl:when test="graph[1]/@color">
     //some processing here using graph[1]/@color values
</xsl:when>

由于你的问题缺少很多重要信息,比如这个 <xsl:when... 出现的上下文,我在这里猜测一下。如果你的评论是正确的,那么你想要做的是处理 graph[1]/xaxis.../yaxis,而不是 graph[1]/@color 的值。


是的。例如,基于属性“颜色”的存在,我需要设置一些变量,比如graph-color。现在我想要一个简单的if-else语句,根据属性是否存在来判断。如果为真,则可以将变量设置为属性中包含的内容。否则,我可以使用默认颜色。 - this-Me
请编辑您的帖子,包括更多的样式表,以便我们可以弄清楚您想要实现什么。 - Jim Garrison

1

我不明白 - 除了一些针对使用apply-templates的轻微语法调整之外:

<xsl:template match="graph[1][@color]">
  <!-- your processing here -->
</xsl:template>

如果不知道你想要做什么,我们就无法提供太多帮助。


我只想根据 XML 文件中是否存在属性“color”来处理图形... - srivatsa
如果(属性存在?)执行过程1;否则执行过程2; - srivatsa
此外,这个图表[1][@color]无法识别属性存在。 - srivatsa
是的,如果graph元素上没有color属性,那么该模板将不会被选中。 - Robert Rossney
是的,这就是重点。那个 XML 文件中可能有也可能没有“color”属性,XSL 必须检查是否存在该属性。 - this-Me

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接