Why can't I get a result from an XPath with namespace in the root element?
这可能是XML命名空间的新手问题,但我不知道如何通过特定的根元素使XPath与以下截短的XML一起使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?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一起正常工作,使其成为:
1 | <CreateOrUpdateEventsRequest> |
否则没有任何效果:
1 2 3 4 | $> @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在应该以
来自www.w3.org:
The XML specification reserves all names beginning with the letters 'x', 'm', 'l' in any combination of upper- and lower-case for use by the W3C. To date three such names have been given definitions—although these names are not in the XML namespace, they are listed here as a convenience to readers and users:
- 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-decl
- xml-stylesheet:请参阅xml-stylesheet处理指令
这里有一些代码需要考虑。从代码开始创建Nokogiri :: XML :: Document:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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) |
这是根节点的名称:
1 | doc.root.name # =>"CreateOrUpdateEventsRequest" |
文档说:
When using CSS, if the namespace is called"xmlns", you can even omit the namespace name.
1 2 3 4 | doc.at('CreateOrUpdateEventsRequest').name # =>"CreateOrUpdateEventsRequest" doc.at('LanguageKey').to_xml # =>"<LanguageKey>\ <IsoCode>en</IsoCode>\ </LanguageKey>" |
使用XPath,我们可以将默认名称空间指定为:
1 2 3 | doc.at('//xmlns:LanguageKey').to_xml # =>"<LanguageKey>\ <IsoCode>en</IsoCode>\ </LanguageKey>" |
有时,如果有很多命名空间,则使用
1 2 3 4 | name_spaces = doc.collect_namespaces # => doc.at('//xmlns:LanguageKey', name_spaces).to_xml # =>"<LanguageKey>\ <IsoCode>en</IsoCode>\ </LanguageKey>" |
您需要浏览Nokogiri :: XML :: Node的文档,以获取有关各种方法的更多信息。
我建议您首先尝试使用CSS选择器,以简化和简化XPath的可读性。我认为XPath具有更多功能,但有时会使我不知所措,因此我更喜欢CSS。
我不使用Nokogiri也不使用Ruby,
但是您需要为名称空间
注册前缀
当我阅读http://nokogiri.org/tutorials/searching_a_xml_html_document.html时
我了解您必须执行类似
的操作
1 | $> @doc.xpath('//dha:LanguageKey', 'dha' => 'http://dhamma.org') |