代码之家  ›  专栏  ›  技术社区  ›  Johan

XSLT,找出最后一个子节点是否是特定元素

  •  9
  • Johan  · 技术社区  · 15 年前

    <foo>some text <bar/> and maybe some more</foo>
    

    <foo>some text <bar/> and a last <bar/></foo>
    

    混合文本节点和 bar 内部元素 foo ,想知道最后一个孩子是不是 酒吧 . 第一个例子应该是错误的,因为后面有文本 ,但第二个例子应该是正确的。

    3 回复  |  直到 10 年前
        1
  •  14
  •   jasso    15 年前

    只需选择 <foo> self 轴来解析节点类型。

    /foo/node()[position()=last()]/self::bar
    

    如果最后一个节点不是元素,则此XPath表达式返回一个空集(相当于布尔值false)。如果你想得到具体的价值 true false ,将此表达式包装到XPath函数中 boolean() . 使用 self::* 而不是 self::bar 匹配任何元素作为最后一个节点。

    <root>
        <foo>some text <bar/> and maybe some more</foo>
        <foo>some text <bar/> and a last <bar/></foo>
    </root>
    

    XSLT文档示例:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:output method="text"/>
    
    <xsl:template match="foo">
        <xsl:choose>
            <xsl:when test="node()[position()=last()]/self::bar">
                <xsl:text>bar element at the end&#10;</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>text at the end&#10;</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    </xsl:stylesheet>
    

    样式表的输出:

    text at the end
    bar element at the end
    
        2
  •  7
  •   Dimitre Novatchev    15 年前

    现在我加入了 foo 如果最后一个孩子是 bar

    使用

    node()[last()][self::bar]
    

    任何非空节点集的布尔值为 true() 是的 false() test 任意属性 <xsl:if> <xsl:when> .

    更好,使用 :

    foo/node()[last()][self::bar]
    

    match 属性 <xsl:template> --因此,你写在纯粹的“推”风格。

        3
  •  5
  •   LarsH    10 年前

    更新: 这个答案解决了原始问题标题“找出最后一个子节点是否是文本节点”中所述的要求。但问题正文提出了一个不同的要求,似乎后一个要求是OP所期望的要求。

    前两个答案明确地测试最后一个孩子是否是一个孩子 bar 元素,而不是直接测试它是否是文本节点。如果foo包含 只有 “混合文本节点和条形图元素” 从来没有孩子。

    1. 样式表逻辑的可读性
    2. 如果元素没有子元素

         test="node()[last()]/self::text()"
    

    <root>
       <foo>some text <bar/> and maybe some more</foo>
       <foo>some text <bar/> and a pi: <?foopi param=yes?></foo>
       <foo>some text <bar/> and a comment: <!-- baz --></foo>
       <foo>some text and an element: <bar /></foo>
       <foo noChildren="true" />
    </root>
    

    使用此XSLT模板:

       <xsl:template match="foo">
          <xsl:choose>
             <xsl:when test="node()[last()]/self::text()">
                <xsl:text>text at the end;&#10;</xsl:text>
             </xsl:when>
             <xsl:when test="node()[last()]/self::*">
                <xsl:text>element at the end;&#10;</xsl:text>
             </xsl:when>
             <xsl:otherwise>
                <xsl:text>neither text nor element child at the end;&#10;</xsl:text>
             </xsl:otherwise>
          </xsl:choose>
       </xsl:template>
    

    产量:

       text at the end;
       neither text nor element child at the end;
       neither text nor element child at the end;
       element at the end;
       neither text nor element child at the end;