3

我正在使用 Crystal,并试图在 XML 文档中检索节点的 ID:

<foo ID="bar"></foo>

我正在使用以下代码获取 ID

require "xml"
file = File.read("path/to/doc.xml")
xml = XML.parse(file)
xpath_context = XML::XPathContext.new(xml)
nodeset = xpath_context.evaluate("//foo/@ID")

如果我检查节点集,我会得到我期望的内容:

[#<XML::Attribute:0x1287690 name="ID" value="bar">]

nodeset.class返回XML::NodeSet一个实例方法[]。所以我相信我应该能够做到这一点来获得价值:

node = nodeset[0]
node.value

但是,当我打电话时,nodeset[0]我收到以下错误:

undefined method '[]' for Float64 (compile-time type is (String | Float64 | Bool | XML::NodeSet))

    node = nodeset[0]

我不明白为什么[]当两者都将节点集视为 Float64inspect并将class其视为XML::Nodeset.

我错过了什么?

String 有[]方法,而 Float64 没有,这是巧合吗?

4

2 回答 2

4

执行evaluate时返回类型是所有可能值的联合类型。在这种情况下XML::NodeSet是运行时类型(注意与编译时类型的区别)。

如果您可以确保返回类型始终是节点集,那么您可以简单地执行以下操作:

nodeset = xpath_context.evaluate("//foo/@ID") as XML::NodeSet

但是,如果结果具有不同的类型,那将引发异常。另一种选择是有条件地这样做:

if nodeset.is_a?(XML::NodeSet)
    # use nodeset here without casting, the compiler will restrict the type
end

甚至有一个case声明:

case nodeset
when XML::NodeSet
  # ...
end
于 2015-09-18T12:44:07.007 回答
0

为了完整起见,这是我在@asterite 和@waj 的帮助下最终得到的代码

file = File.read("path/to/doc.xml")
xml = XML.parse(file)
node = xml.xpath_node("//foo/@ID")
node.text

请注意 node.value 也是错误的!

于 2015-09-18T13:16:01.900 回答