0

这可能是一个 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 处理这样的命名空间?

4

3 回答 3

1

非常感谢您的帮助。

答案似乎是,当 XML 应该声明带有前缀的命名空间时,XML 重新声明了xmlns:myns.

来自 www.w3.org:

XML 规范保留所有以字母“x”、“m”、“l”开头的名称,以任何大小写组合形式供 W3C 使用。迄今为止,已经定义了三个这样的名称——尽管这些名称不在 XML 命名空间中,但为了方便读者和用户,在此列出它们:

于 2013-07-21T23:38:21.567 回答
0

这是一些需要考虑的代码。从创建 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。

于 2013-07-18T04:40:22.707 回答
0

我不使用 Nokogiri 或 Ruby,但您需要为命名空间注册一个前缀http://dhamma.org

当我阅读http://nokogiri.org/tutorials/searching_a_xml_html_document.html 我明白你必须做类似的事情

$> @doc.xpath('//dha:LanguageKey', 'dha' => 'http://dhamma.org')
于 2013-07-18T00:26:21.073 回答