REXML 无法从属性中进行选择。 Bug 或者不正确的 XPath?

发布于 2024-10-15 21:32:23 字数 895 浏览 5 评论 0原文

我尝试通过特殊属性从 SVG 文档中选择一个元素。 我设置了一个简单的例子。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
  <g id='1'>
    <path id='2' type='A'/>
    <rect id='3' type='B'/>
  </g>
</svg>

现在,我使用以下语法通过属性“type”检索路径元素:

require 'rexml/document'
include REXML
xmlfile = File.new "xml_as_specified_above.svg"
xmldoc = Document.new(xmlfile)
XPath.match( xmldoc.root, "//path[@type]" )

直接来自 http 的语法: //www.w3schools.com/xpath/xpath_syntax.asp。 我希望这个表达式选择路径元素,但如下所示:

>> XPath.match( xmldoc.root, "//path[@type]" )
=> []

那么,XPath 中通过其属性寻址路径元素的正确语法是什么? 或者 REXML 中是否存在错误(使用 3.1.7.3)? 加分还可以检索“rect”元素。

I try to select an element from an SVG document by a special attribute.
I set up a simple example.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
  <g id='1'>
    <path id='2' type='A'/>
    <rect id='3' type='B'/>
  </g>
</svg>

Now I use the following syntax to retrieve the path element by its attribute "type":

require 'rexml/document'
include REXML
xmlfile = File.new "xml_as_specified_above.svg"
xmldoc = Document.new(xmlfile)
XPath.match( xmldoc.root, "//path[@type]" )

Syntax directly from http://www.w3schools.com/xpath/xpath_syntax.asp.
I would expect that this expression selects the path element but this is what follows:

>> XPath.match( xmldoc.root, "//path[@type]" )
=> []

So, what is the correct syntax in XPath to address the path element by it's attribute?
Or is there a bug in REXML (using 3.1.7.3)?
Plus points for also retrieving the "rect" element.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浮世清欢 2024-10-22 21:32:23

看起来正在使用旧版本的 rexml,它不支持完整的 XPath 规范。

尝试检查 puts XPath::VERSION 的输出以确保显示 3.1.73。

It looks like an older version of rexml is being picked up that doesn't support the full XPath spec.

Try checking the output of puts XPath::VERSION to ensure that 3.1.73 is displayed.

反话 2024-10-22 21:32:23

您需要考虑默认名称空间。使用 XPath 1.0,您需要将前缀(例如 svg)绑定到命名空间 URI http://www.w3.org/2000/svg,然后使用类似的路径//svg:path[@type]。如何将前缀绑定到 URI 以进行 XPath 评估取决于您使用的 XPath API,如果您在 API 文档中找不到方法或属性,恐怕我不知道您的 Ruby API 是如何完成的你自己,然后也许会有其他人稍后来告诉我们。

You need to take the default namespace into account. With XPath 1.0 you need to bind a prefix (e.g. svg) to the namespace URI http://www.w3.org/2000/svg and then use a path like //svg:path[@type]. How you bind a prefix to a URI for XPath evaluation depends on the XPath API you use, I am afraid I don't know how that is done with your Ruby API, if you don't find a method or property in the API documentation yourself then maybe someone else comes along later to tell us.

停滞 2024-10-22 21:32:23

如今,我们中的许多人都使用 Nokogiri,而不是 ReXML 或 Hpricot(另一种早期的 Ruby XML 解析器)。

Nokogiri 支持 XPath 和 CSS 访问器,因此您可以使用熟悉的 HTML 类型路径来获取节点:

require 'nokogiri'

svg = %q{<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
  <g id='1'>
    <path id='2' type='A'/>
    <rect id='3' type='B'/>
  </g>
</svg>
}

doc = Nokogiri::XML(svg)
puts doc.search('//svg:path[@type]')
puts doc.search('svg|path[@type]')
puts doc.search('path[@type]')

puts doc.search('//svg:rect')
puts doc.search('//svg:rect[@type]')
puts doc.search('//svg:rect[@rect="B"]')
puts doc.search('svg|rect')
puts doc.search('rect')

# >> <path id="2" type="A"/>
# >> <path id="2" type="A"/>
# >> <path id="2" type="A"/>

# >> <rect id="3" type="B"/>
# >> <rect id="3" type="B"/>
# >> <rect id="3" type="B"/>
# >> <rect id="3" type="B"/>

第一个路径是带有命名空间的 XPath。第二个是带有命名空间的 CSS。第三种是没有命名空间的CSS。 Nokogiri 对人类很友好,将允许我们通过几种方式处理和免除命名空间,假设我们知道为什么命名空间是好的。

Many of us use Nokogiri these days instead of ReXML or Hpricot, another early Ruby XML parser.

Nokogiri supports both XPath, and CSS accessors, so you can use familiar HTML type paths to get at nodes:

require 'nokogiri'

svg = %q{<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
  <g id='1'>
    <path id='2' type='A'/>
    <rect id='3' type='B'/>
  </g>
</svg>
}

doc = Nokogiri::XML(svg)
puts doc.search('//svg:path[@type]')
puts doc.search('svg|path[@type]')
puts doc.search('path[@type]')

puts doc.search('//svg:rect')
puts doc.search('//svg:rect[@type]')
puts doc.search('//svg:rect[@rect="B"]')
puts doc.search('svg|rect')
puts doc.search('rect')

# >> <path id="2" type="A"/>
# >> <path id="2" type="A"/>
# >> <path id="2" type="A"/>

# >> <rect id="3" type="B"/>
# >> <rect id="3" type="B"/>
# >> <rect id="3" type="B"/>
# >> <rect id="3" type="B"/>

The first path is XPath with the namespace. The second is CSS with a namespace. The third is CSS without namespaces. Nokogiri, being friendly to humans, will allow us to deal and dispense with the namespaces a couple ways, assuming we are aware of why namespaces are good.

半夏半凉 2024-10-22 21:32:23

这是最常见的FAQ:默认命名空间问题。

解决方案:

代替:

//path[@type]

使用

//svg:path[@type]

This is the most FAQ: default namespace issue.

Solution:

Instead of:

//path[@type]

use

//svg:path[@type]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文