1

我尝试通过特殊属性从 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”元素。

4

4 回答 4

3

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

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

于 2011-02-04T13:27:47.777 回答
0

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

于 2011-02-04T12:58:37.067 回答
0

如今,我们中的许多人都使用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 将允许我们以几种方式处理和免除命名空间,假设我们知道为什么命名空间是好的。

于 2011-02-04T13:44:21.530 回答
0

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

解决方案:

代替:

//path[@type]

采用

//svg:path[@type]
于 2011-02-04T15:37:29.923 回答