这可能是一个XML命名空间新手的问题,但我不知道如何让XPath使用以下带有特定根元素的截断XML:
<?xml version="1.0" encoding="UTF-8"?>
<CreateOrUpdateEventsRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://dhamma.org" version="3-0-0">
<LanguageKey>
<IsoCode>en</IsoCode>
</LanguageKey>
<Publish>
<Value>true</Value>
</Publish>
<Events>
<Event>
<EventKey>
<LocationKey>
<SubDomain>rasmi</SubDomain>
</LocationKey>
<EventId>10DayPDFStdTag</EventId>
</EventKey>
</Event>
</Events>
</LanguageKey>
</CreateOrUpdateEventsRequest>
使用Ruby和Nokogiri(带有刚刚更新的libxml2),只有当我删除根元素中的所有额外信息时,它才能很好地使用XPath,使其成为:
<CreateOrUpdateEventsRequest>
否则什么都不起作用:
$> @doc.xpath("//CreateOrUpdateEventsRequest") #=> [] with original header, an array of nodes with modified header
$> @doc.xpath("//LanguageKey") #=> [] with the original header, an array of nodes with modified header
$> @doc.xpath("//xmlns:LanguageKey") #=> undefined namespace prefix with the original
如何使用XPath处理这样的名称空间?
非常感谢您的帮助。
答案似乎是,XML在本应声明带有前缀的名称空间(如xmlns:myns
)时,重新声明了XMLNS。
来自www.w3.org:
XML规范保留所有以字母"x"、"m"、"l"开头的名称,大小写任意组合,供W3C使用。到目前为止,已经给出了三个这样的名称的定义——尽管这些名称不在XML名称空间中,但为了方便读者和用户,这里列出了它们:
- xml:请参阅http://www.w3.org/TR/xml/#NT-XMLDecl和http://www.w3.org/TR/xml-names/#xmlReserved
- xmlns:请参阅http://www.w3.org/TR/xml-names/#ns-下降
- xml样式表:请参阅xml样式表处理说明
我既不使用Nokogiri也不使用Ruby,但是您需要为命名空间http://dhamma.org
注册一个前缀
当我读书的时候http://nokogiri.org/tutorials/searching_a_xml_html_document.html我知道你必须做一些类似的事情
$> @doc.xpath('//dha:LanguageKey', 'dha' => 'http://dhamma.org')
下面是一些需要考虑的代码。从创建Nokogiri::XML::Document:的代码开始
require 'nokogiri'
XML = <<EOT
<?xml version="1.0" encoding="UTF-8"?>
<CreateOrUpdateEventsRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://dhamma.org" version="3-0-0">
<LanguageKey>
<IsoCode>en</IsoCode>
</LanguageKey>
<Publish>
<Value>true</Value>
</Publish>
<Events>
<Event>
<EventKey>
<LocationKey>
<SubDomain>rasmi</SubDomain>
</LocationKey>
<EventId>10DayPDFStdTag</EventId>
</EventKey>
</Event>
</Events>
</LanguageKey>
</CreateOrUpdateEventsRequest>
EOT
doc = Nokogiri::XML(XML)
这是根节点的名称:
doc.root.name # => "CreateOrUpdateEventsRequest"
医生说:
使用CSS时,如果名称空间被称为"xmlns",您甚至可以省略名称空间名称。
doc.at('CreateOrUpdateEventsRequest').name # => "CreateOrUpdateEventsRequest"
doc.at('LanguageKey').to_xml # => "<LanguageKey>n <IsoCode>en</IsoCode>n </LanguageKey>"
使用XPath,我们可以将默认名称空间指定为:
doc.at('//xmlns:LanguageKey').to_xml # => "<LanguageKey>n <IsoCode>en</IsoCode>n </LanguageKey>"
有时,如果有很多名称空间,那么使用collect_namespaces
并传入它们是有意义的:
name_spaces = doc.collect_namespaces # =>
doc.at('//xmlns:LanguageKey', name_spaces).to_xml # => "<LanguageKey>n <IsoCode>en</IsoCode>n </LanguageKey>"
您需要查看Nokogiri::XML::Node的文档,以获取有关各种方法的更多信息。
作为第一次尝试,我建议使用CSS选择器来简化和易读XPath。我认为XPath有更多的功能,但它有时会让我眼睛发呆,所以我更喜欢CSS。