用于选择前面元素以及可选的纯空白文本节点的 XPath

2023-12-20

给定一个元素作为上下文,我想选择前面的同级元素并检查它是否具有特定名称。需要注意的是,如果存在包含非空白内容的中间文本节点,我不想选择它。

例如,给定这个 XML 文档...

<r>
  <a>a1</a><a>a2</a>
   b
  <a>a3</a>
    <a>a4</a>
  <b/>
  <a>a5</a>
</r>

…then:

  • 对于“a1”应该没有匹配项(没有<a>紧邻其前面的兄弟元素)
  • 对于“a2”,则应匹配“a1”(没有中间文本节点)
  • 对于“a3”应该没有匹配项(中间有一个包含非空白内容的文本节点)
  • 对于“a4”,则应匹配“a3”(中间的文本节点仅为空格)
  • 对于“a5”,不应有匹配项(前面的同级元素不是<a>).

我可以检查前面的兄弟是否是<a> with preceding-sibling::*[1][name()="a"]

但是,我不知道怎么说“选择以下同级节点,无论元素或文本性如何,然后看看它是否不是文本或normalize-space(.)=""。我最好的猜测是:

preceding-sibling::*[1][name()="a"][following-sibling::node()[1][not(text()) or normalize-space(.)=""]]

……但这似乎没有效果。


这是我的测试 Ruby 文件:

require 'nokogiri'

xpath = 'preceding-sibling::*[1][name()="a"][following-sibling::node()[1][not(text()) or normalize-space(.)=""]]'
fragment = Nokogiri::XML.fragment '<a>a1</a><a>a2</a> b <a>a3</a> <a>a4</a> <b/> <a>a5</a>'    

fragment.css('a').each{ |a| p [a.text,a.xpath(xpath).to_s] }
#=> ["a1", ""]
#=> ["a2", ""]
#=> ["a3", "<a>a2</a>"]
#=> ["a4", "<a>a3</a>"]
#=> ["a5", ""]

“a2”和“a3”的结果是错误的并且让我感到困惑。它找到前面的<a>正确,但随后无法正确验证其第一个后续兄弟是否不是文本(这应该允许“a2”找到“a1”)或者它只是空白(这应该阻止“a3”找到“a2” ”。


Edit:这是我正在编写的 XPath,以及我想要它做什么:

  • preceding-sibling::*[1][name()="a"]…- 找到第一个前面的元素,并确保它是一个<a>. 这似乎正在按预期工作。

    • [following-sibling::node()[1][…]]- 确保第一个后续节点(找到的前面的<a>) 匹配一些条件

      • not(text()) or normalize-space(.)=""- 确保以下节点不是文本节点,或者其规范化空间为空

Use:

/*/a/preceding-sibling::node()
       [not(self::text()[not(normalize-space())])]
            [1]
              [self::a]

基于 XSLT 的验证:

<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="/">
     <xsl:copy-of select=
       "/*/a
          /preceding-sibling::node()
                      [not(self::text()[not(normalize-space())])]
                                        [1]
                                         [self::a]
    "/>
 </xsl:template>
</xsl:stylesheet>

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

<r>
  <a>a1</a><a>a2</a>
   b
  <a>a3</a>
    <a>a4</a>
  <b/>
  <a>a5</a>
</r>

对 XPath 表达式进行求值,并将此求值选择的节点复制到输出:

<a>a1</a>
<a>a3</a>

Update:

问题中的 XPath 表达式有什么问题?

问题就在这里:

[not(text()) or normalize-space(.)='']

这测试上下文节点是否没有文本节点child.

但是OP想要测试上下文节点是否is一个文本节点。

Solution:

将上面的内容替换为:

[not(self::text()) or normalize-space(.)='']

基于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="/*/a">
     <xsl:copy-of select=
     "preceding-sibling::*[1]
                      [name()='a']
                         [following-sibling::node()[1]
                                    [not(self::text()) or normalize-space(.)='']
                       ]"/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

现在这个转换正好产生了想要的结果:

<a>a1</a>
<a>a3</a>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于选择前面元素以及可选的纯空白文本节点的 XPath 的相关文章

  • 帮助重构这个讨厌的 Ruby if/else 语句

    所以我有这个大而多毛的 if else 语句 我将跟踪号码传递给它 然后它确定它是什么类型的跟踪号码 我怎样才能简化这件事 具体来说就是想减少代码行数 if num length lt 8 tracking service false el
  • 用于从链接中选择文本的 xpath 表达式

    我有这样的html文件内容 a class bf title Link to book href book 229920 book name a 帮我构造 xpath 表达式来获取链接文本 书名 我尝试使用 a 但表达式计算时没有结果 如果
  • Rails3 SQL 日志记录输出在单独的文件中

    我希望将所有 ActiveRecord SQL 日志记录重定向到不同的文件中 将其放在控制台或 log development log 中有点混乱 怎么做 我希望将其放在 log development sql log 文件中 Thanks
  • 检查数组元素的大小是否相同

    有没有最好 最有效的方法来检查数组元素的大小是否相同 1 2 3 4 5 gt false 1 2 3 4 5 6 gt true 我有什么 def element of same size arr arr map size uniq si
  • 与 Array 相比,使用 Ruby NArray 有哪些优点?

    我刚刚遇到了 Ruby 的 NArray 库 请原谅我在问这个问题时的无知 与标准 Ruby Array 实现相比 使用 NArray 库有哪些优点 我已经看到 NArray 是面向数值计算的 但是看看 API 看起来好像只有一些针对数值的
  • Ruby,通过 SSH 和 LOG 逐一运行 linux 命令

    我想用 Ruby 女巫 net ssh 编写代码 在远程 Linux 机器上一一运行命令并记录所有内容 在 Linux 机器上称为命令 stdout 和 stderr 所以我写函数 def rs ssh cmds cmds each do
  • 是否可以在 proc 中查看 ruby​​ 代码?

    p Proc new puts ok 是否可以在过程中看到 ruby 代码 inspect返回内存位置 puts p inspect
  • Ruby on Rails 中的枚举

    我是一名 C 程序员 我正在研究 ruby on Rails 但我可能在心态或其他方面遇到了一些麻烦 我有一个投票对象 该对象可以是赞成 中立或反对 我通常会让投票对象有一个像这样的字段 private VoteEnum voteEnum
  • 如何清除 ruby​​ 中 rspec 测试之间的类变量

    我有以下课程 我想确保类 url 只为所有实例设置一次 class DataFactory url nil def initialize begin if url nil Rails logger debug Setting url url
  • Rails 5.2 Active Storage 添加自定义属性

    我有一个带有附件的模型 class Project lt ApplicationRecord has many attached images end 当我附加并保存图像时 我还想保存一个附加的自定义属性 display order 整数
  • 如何防止 .NET 中的 XPath/XML 注入

    如何防止 NET Framework 中的 XPATH 注入 我们之前使用字符串连接来构建 XPATH 语句 但发现最终用户可以执行一些任意 XPATH 例如 string queryValue pages url USER INPUT V
  • 为 .API 文件启用自动完成功能?

    有谁知道如何使用 N 站点上提供的 API 文件在 Notepad 中自动完成工作 在 API 文件夹中具有 XML 自动完成文件的语言中 自动完成功能工作得很好 但对于使用 API 文件的语言 ruby AutoIt 等 完全不起作用 根
  • 在所有延迟的作业之前挂钩

    是否可以在所有delayed job任务之前运行一个方法 基本上 我们试图确保每台运行delayed job的服务器都有我们代码的最新实例 因此我们希望运行一个方法来在每个作业运行之前检查这一点 我们已经有了 check 方法并在其他地方使
  • 如何使用 minitest 运行所有测试?

    我下载了一个项目的源代码 发现了一个错误并修复了它 现在我想运行测试来看看我是否破坏了任何东西 测试是在 minitest DSL 中进行的 我如何同时运行它们 我搜索了适用的 rake 任务等 但没有找到 这是一个链接耙子 测试任务 ht
  • 如何在 Rails 3 中连接表并计算记录数?

    我有一个Collection有很多硬币的类 我正在尝试选择拥有两枚以上硬币的收藏品 目前 我可以直接通过 Ruby 来完成此操作 但效率极低 我当前的代码 collections Collection all select c c coin
  • 如何使用define_method创建类方法?

    如果您尝试以元编程方式创建类方法 这非常有用 def self create methods method name To create instance methods define method method name do end T
  • 如何阻止“gem”实用程序访问我的主目录?

    当我跑步时 gem install
  • xQuery LIKE 运算符?

    有没有办法以与 SQL 相同的方式使用 XQuery 执行 LIKE 操作 我不想构造一些 startswith endswith 和 contains 表达式 我想要实现的目标的示例 for x in user where x first
  • Rails 3:用户创建自定义表单?

    我正在尝试思考如何允许用户创建具有所有字段类型的自定义表单 如果有一颗宝石那就太好了 但我似乎无法在任何地方找到它 所以我有一个像这样的数据库设置 t integer form id t string name t string hint
  • 为什么每个方法需要将其循环的值分配给变量?

    在 Rails 上工作 发现我对 Rails 的理解缺乏知识each method 不知道为什么each方法需要变量 message h2 h2 不确定为什么每个方法都需要变量 message 事实并非如此require它 你完全可以忽略它

随机推荐