【问题标题】:Why can't I get a result from an XPath with namespace in the root element? [duplicate]为什么我不能从根元素中带有命名空间的 XPath 获得结果? [复制]
【发布时间】:2013-07-16 17:40:14
【问题描述】:

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

【问题讨论】:

    标签: ruby xml xpath namespaces nokogiri


    【解决方案1】:

    非常感谢您的帮助。

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

    来自 www.w3.org:

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

    【讨论】:

      【解决方案2】:

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

      当我读到http://nokogiri.org/tutorials/searching_a_xml_html_document.html 我知道你必须做类似的事情

      $> @doc.xpath('//dha:LanguageKey', 'dha' => 'http://dhamma.org')
      

      【讨论】:

        【解决方案3】:

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

        The docs说:

        使用 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。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-10-23
          • 1970-01-01
          • 2012-04-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多