使用XPath从XML文档的另一部分中查找其属性缺失的节点

时间:2014-03-10 20:01:29

标签: xml xslt xpath

我有一个类似于此的XML文档:

<pipeline>
    <log>
        <error stageName="One" message="Ack!" />
        <error stageName="Two" message="Ack!" />
        <error stageName="Three" message="Ack!" />
    </log>
    <stages>
        <stage name="One" />
        <stage name="Two" />
    </stages>
</pipeline>

我尝试使用XSLT报告按阶段分组的所有错误。在报告的最后,我希望所有与任何阶段无关的错误。我能够报告每个阶段的错误。现在我需要一种方法来有条件地显示所有其他错误。

这是我最接近的:

<xsl:template match="/pipeline">
    <xsl:variable name="unknown.stages" 
                  select="log/error[@stageName != stages/stage/@name]" />

    <xsl:if test="count($unknown.stages) > 0">
        <h1>Other Errors</h1>
        <xsl:apply-templates select="$unknown.stages" />
    </xsl:if>
</xsl:template>

但它最终会显示所有错误,而不仅仅是与舞台无关的错误。是否存在我可以在xsl:variable声明中使用的XPath查询,以选择error属性具有stageName列表中不存在的值的所有stages/stage个节点元素?

更新:这是正确的XPath查询。我必须在舞台元素上创建一个键,然后使用该键找到不匹配的错误:

<xsl:key name="stageName" match="/pipeline/stages/stage" use="@name" />

<xsl:template match="/pipeline">
    <xsl:variable name="unknown.stages" 
                  select="log/error[not(key('stageName',@stageName)]" />

    <xsl:if test="count($unknown.stages) > 0">
        <h1>Other Errors</h1>
        <xsl:apply-templates select="$unknown.stages" />
    </xsl:if>
</xsl:template>

1 个答案:

答案 0 :(得分:1)

您确定要显示所有错误吗?使用当前的xpath,它将查找阶段元素,该元素是您选择的当前错误元素的子元素。我原以为表达式看起来更像是

<xsl:variable name="unknown.stages" select="log/error[@stageName != //stages/stage/@name]" />

话虽如此,这会返回所有错误元素,因为它返回错误元素,其中存在具有不同名称的阶段

无论如何,要解决此问题,请考虑使用密钥查找阶段元素

<xsl:key name="stages" match="stage" use="@name" />

然后你可以像这样编写你的表达式,它应该根据你的要求检查是否存在:

<xsl:variable name="unknown.stages"select="log/error[not(key('stages', @stageName))]" />