【问题标题】:XPath - Return Null if single instance of element contains specific textXPath - 如果元素的单个实例包含特定文本,则返回 Null
【发布时间】:2013-01-06 20:38:37
【问题描述】:

在 XML 文档中,例如:

<a>
  <b>
    <c>Text1</c>
    ...
  </b>
  <b>
    <c>Text2</c>
    ...
  </b>
  ...
</a>

什么是单个 XPath 1.0 兼容、本地命名空间()兼容的表达式,如果任何元素包含“Text1”的内部文本,则返回 Null 集。

我尝试了许多不同的表达式,但无法获取会返回空集的元素。

例如

//*[local-name()='c' and .='Text1']

- or -   

/*[local-name()='a']/*[local-name()='b']/*not(local-name()='c' and .='Text1'])

严格要求是由于 .NET 函数调用 XmlNode.SelectSingleNode 方法(字符串)的特定实现

最终精确解 礼貌迪米特

/*[not(//*[local-name()='c' and . = 'Text1'])]

【问题讨论】:

    标签: .net xml xpath xmlnode xpath-1.0


    【解决方案1】:

    什么是单一的 XPath 1.0 兼容、本地命名空间()兼容、 如果任何元素包含内部文本,则表达式返回 Null 集 'Text1'。

    如果没有这样的c 元素,您还没有指定应该选择什么,所以下面我在这种情况下选择顶部元素。

    使用

    /*[not(//c[. = 'Text1'])]
    

    如果 XML 文档中有 c 元素,其字符串值为“Text1”,则不会选择任何内容。

    在使用默认命名空间的情况下,这将被写为

    /*[not(//*[name()='c' and . = 'Text1'])]
    

    基于 XSLT 的验证

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="/">
         <xsl:copy-of select="/*[not(//c[. = 'Text1'])]"/>
     </xsl:template>
    </xsl:stylesheet>
    

    当此转换应用于提供的 XML 文档时:

    <a>
      <b>
        <c>Text1</c>
        ...
      </b>
      <b>
        <c>Text2</c>
        ...
      </b>
      ...
    </a>
    

    XPath 表达式被求值,并且该求值的结果被复制到输出中——在这种情况下没有产生任何东西——正如预期的那样

    如果我们把上面的XML文档改成

    <a>
      <b>
        <c>Text3</c>
        ...
      </b>
      <b>
        <c>Text2</c>
        ...
      </b>
      ...
    </a>
    

    则条件为true(),求值结果为以顶部元素为根的子树

    <a>
        <b>
            <c>Text3</c>
        ...
        </b>
        <b>
            <c>Text2</c>
        ...
        </b>
      ...
    </a>
    

    【讨论】:

    • 我感觉这就是我要找的东西(虽然,使用 local-name() 而不是 name()),但我不断收到无效令牌错误。想法?
    • @Jonathan,解决方案正确的——我将在几分钟后发布基于 XSLT 的验证。每个人都可以运行它,看看是否产生了正确的结果。
    • @Jonathan,完成。您可以自己运行转换并查看 XPath 表达式是否具有所需的结果。
    • @Dmitre,逻辑是正确的,但是 name() 函数在实现中没有考虑到一些相当有限的命名空间处理。但是,将 name() 更改为 local-name() 实际上无需任何其他修改即可工作。干杯!
    • @Jonathan,不客气。至于命名空间处理,提供的 XML 文档中没有特殊的命名空间,我不想对真实文档进行猜测。
    【解决方案2】:

    否定你的表达方式

    not(//*[local-name()='c' and .='Text1'])
    

    如果没有&lt;c&gt;Text1&lt;/c&gt;,则返回true,否则不返回任何内容。

    【讨论】:

    • 感谢您的回复。但是,我在这里担心的是它必须返回一组元素,并且不能返回布尔值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 2016-02-07
    • 2020-09-27
    • 2017-09-20
    • 1970-01-01
    相关资源
    最近更新 更多