我有一些XML:
<sys>
<lang>
<employee>
<name>Employee 1</name>
<code>4fdaa994-7015-4ec1-b365-de4ee0279966</code>
</employee>
<employee>
<name>Employee 2</name>
<code>1d960bdc-0853-49af-bb83-18cf92493897</code>
</employee>
</lang>
</syz>
如何搜索员工节点name ="Employee 1"
?
我尝试了这个,但它不起作用:
obj.xpath("//sys/lang[/employee/name = 'Employee 1']")
答案 0 :(得分:3)
此XPath
/sys/lang/employee[name = 'Employee 1']
将选择employee
为name
的<{1}}元素。
为什么OP可能会使用上述XPath获得“无效表达式”?
转录错误。
解决方案:使用复制和粘贴。
单引号附近的单引号。
解决方案:使用外部双引号:Employee 1
智能引号。
解决方案:将"/sys/lang/employee[name = 'Employee 1']"
和‘
替换为单引号’
。
错误解释错误消息。
解决方案:仔细检查错误中提到的任何行号,或尽可能多地删除周围的代码,并查看错误是否消失。
如果上述任何一种可能性都不适用,请发布MCVE(Minimal, Complete, and Verifiable Example,包括提供的XPath 和主叫代码 - 完成 在MCVE中)产生无效的表达错误,有人可能会立即发现问题。
答案 1 :(得分:1)
出于可读性原因,我非常喜欢使用CSS而不是XPath。 Nokogiri实现了许多jQuery的扩展,使我们可以更容易地将CSS用于我们通常使用XPath的东西。
我这样做:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<sys>
<lang>
<employee>
<name>Employee 1</name>
<code>4fdaa994-7015-4ec1-b365-de4ee0279966</code>
</employee>
<employee>
<name>Employee 2</name>
<code>1d960bdc-0853-49af-bb83-18cf92493897</code>
</employee>
</lang>
</syz>
EOT
emp1 = doc.at('employee name:contains("Employee 1")') # => #<Nokogiri::XML::Element:0x3ffed05285b4 name="name" children=[#<Nokogiri::XML::Text:0x3ffed05283d4 "Employee 1">]>
emp1.to_xml # => "<name>Employee 1</name>"
emp1.parent.to_xml # => "<employee>\n <name>Employee 1</name>\n <code>4fdaa994-7015-4ec1-b365-de4ee0279966</code>\n </employee>"
另请注意,在节点的选择器中定义完整路径并不是一种好习惯。如果HTML或XML更改了选择器将中断的结构。相反,找到有用的地标并从一个跳到下一个。这样,您的选择器更有可能在标记中发生变化。我只关心找到合适的<employee>...<name>
组合,而不是<sys>
和<lang>
下嵌入的那两个标签。
有时,另一种获取所需信息的方法是使用search
并查看特定索引:
doc.search('employee').first.to_xml # => "<employee>\n <name>Employee 1</name>\n <code>4fdaa994-7015-4ec1-b365-de4ee0279966</code>\n </employee>"
或者:
doc.at('employee').to_xml # => "<employee>\n <name>Employee 1</name>\n <code>4fdaa994-7015-4ec1-b365-de4ee0279966</code>\n </employee>"
at('some selector')
相当于search('some selector').first
。