【问题标题】:Locating the node by value containing whitespaces using XPath使用 XPath 按包含空格的值定位节点
【发布时间】:2008-12-26 14:35:12
【问题描述】:

我需要使用 XPath 通过其值在 xml 文件中定位节点。 当要查找的节点包含内部带有空格的值时,就会出现问题。 F.e.:

<Root>
  <Child>value</Child>
  <Child>value with spaces</Child>
</Root>

我无法构造定位第二个子节点的 XPath。

简单的 XPath /Root/Child 完美适用于两个孩子,但 /Root[Child=value with spaces] 返回一个空集合。

我已经尝试使用 %20& #20;& nbsp; 以及使用引号和双引号来屏蔽空格。

还是没有运气。

有人有想法吗?

【问题讨论】:

    标签: xpath whitespace


    【解决方案1】:

    根据您的具体情况,有不同的 XPath 表达式将选择节点,其值包含一些空格。

    首先,让我们回忆一下这些字符中的任何一个都是“空白”:

        &amp;#x09; -- 标签

        &amp;#xA; -- 换行

        &amp;#xD; -- 回车

        ' '&amp;#x20; -- 空格

    如果你知道节点的确切值,说它是“Hello World”加一个空格,那么最直接的 XPath 表达式:

         /top/aChild[. = 'Hello World']

    将选择此节点。

    然而,指定一个包含空格的值的困难在于,我们将所有的空格字符都视为......好吧,空格并且不知道它是否是一个一组空格或一个制表符。

    XPath 2.0 中可以使用regular expressions,它们提供了一种简单方便的解决方案。因此我们可以使用如下的 XPath 2.0 表达式:

        /*/aChild[matches(., "Hello\sWorld")]

    选择顶部节点的任何子节点,其值为字符串“Hello”后跟空格,后跟字符串“World”。 注意使用matches() 函数和匹配空格的“\s”模式。

    XPath 1.0中,如果给定字符串包含任何空白字符,一个方便的测试是:

    not(string-length(.)= stringlength(translate(., ' &amp;#9;&amp;#xA;&amp;#xD;','')))

    这里我们使用translate() 函数消除四个空白字符中的任何一个,并将结果字符串的长度与原始字符串的长度进行比较。

    因此,如果在文本编辑器中,节点的值显示为

    “你好    世界”,

    我们可以使用 XPath 表达式安全地选择这个节点:

    /*/aChild[translate(., ' &amp;#9;&amp;#xA;&amp;#xD;','') = 'HelloWorld']

    在许多情况下,我们还可以使用 XPath 函数normalize-space(),它从其字符串参数生成另一个字符串,其中前导和尾随空白组被剪切,并且字符串中的每个空白都被单个空格替换。

    在上述情况下,我们将简单地使用以下 XPath 表达式:

    /*/aChild[normalize-space() = 'Hello World']

    【讨论】:

    • @DimitreNovaatchev 您能否提供一个文档,其中可以找到此类编码列表,例如 -- 选项卡.
    • @Babai,空白字符就是这三个:
    • @DimitreNovaatchev 我正在为其他人谈论更多......好吧。感谢您的及时回复.. 有一个很好的question。你能帮助 OP.. 我正在尝试但无法制定.. 先生你有时间吗?
    • @Babai,不幸的是这些天我很忙。您需要查看 Unicode 标准 (unicode.org)
    • @DimitreNovaatchev 我试过这个concat(string(//textarea[@name="command"]/text()),'&amp;#xA;'),但没有发生,我得到了1&amp;#xA;.. 如何使用 xpath 向字符串添加换行符?
    【解决方案2】:

    试试这个:

    /Root/Child[normalize-space(text())=value without spaces]
    

    /Root/Child[contains(text(),value without spaces)]
    

    或者(因为看起来你的测试值可能是问题)

    /Root/Child[normalize-space(text())=normalize-space(value with spaces)]
    

    实际上并没有执行任何这些,所以语法可能很不稳定。

    【讨论】:

    • Dimitre Novatchev 的回答是彻底的,但我认为在大多数情况下它是矫枉过正的。我赞成这个答案,因为它更简单并且适用于大多数情况。好吧,至少在精神上:-)——函数是 normalize-space() 而不是 normalize()。请参阅:normalize-space 函数的官方文档。
    【解决方案3】:

    使用 XPath 按包含空格的值定位属性

    我有一个输入类型元素,其值包含空格。

    例如:

    <input type="button"  value="Import&nbsp;Selected&nbsp;File">
    

    我通过使用这个 xpath 表达式解决了这个问题。

    //input[contains(@value,'Import') and contains(@value ,'Selected')and contains(@value ,'File')]
    

    希望对大家有所帮助。

    【讨论】:

    • 好吧,它也将匹配“文件选择导入”,这有时可能是一个陷阱,在我的情况下肯定是不可取的。
    【解决方案4】:

    你尝试过#x20 吗?

    【讨论】:

      【解决方案5】:

      我已经在second link 上搜索了这个:

      尝试使用“x0020”替换空格

      这似乎对那个人有用。

      【讨论】:

        【解决方案6】:

        "x0020" 在基于 jackrabbit 的 CQ5/AEM 存储库中为我工作,其中属性名称有空格。以下适用于属性“记录 ID”-

        [(jcr:contains(jcr:content/@Record_x0020_ID, 'test'))]
        

        【讨论】:

          【解决方案7】:

          上述所有解决方案都对我不起作用。 但是,有一个更简单的解决方案。

          创建 XMLDocument 时,确保将 PreserveWhiteSpace 属性设置为 true;

                  XmlDocument xmldoc = new XmlDocument();
                  xmldoc.PreserveWhitespace = true;
                  xmldoc.Load(xmlCollection);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-05-22
            • 2021-06-09
            • 1970-01-01
            • 2011-07-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多