【问题标题】:How do I query elements containing attributeNameA with namespaceB with "css"?如何使用“css”查询包含 attributeNameA 和 namespaceB 的元素?
【发布时间】:2012-01-06 16:25:59
【问题描述】:

我的问题与“How can I get the values of attributes with namespace, using Nokogiri?”不同。

我的 XML 包含带有命名空间的属性。如何使用 Nokogiri 的 css 方法查询包含 attributeNameA 和 namespaceB (namespaceB:attributeNameA="attributeAValue") 的元素?

这是我的代码:

xmlContent = %Q|
<?xml version="1.0"?>
<ns1:el1 xmlns:ns1="blabla" >
    <ns1:el2 ns1:att="123">with namespace</ns1:el2 >
    <ns1:el2 att="noNameSpace">no namespace</ns1:el2 >
</ns1:el1>|
xml_doc  = Nokogiri::XML(xmlContent)

#no namespace
result = xml_doc.css('ns1|el2[att]')
result.each {|i| puts i}

#with namespace
result = xml_doc.css('ns1|el2[ns1|att]') #error unexpexted '|'
result.each {|i| puts i}

2011 年 1 月 6 日编辑: 从这个链接: https://github.com/tenderlove/nokogiri/issues/257#issuecomment-3365636Nokogiri 不支持直接查询带有命名空间属性的xml元素。

真正的用例是修改 SSIS 包 (*.dtsx);我无法查询属性 DTS:Name 包含“projectVar_”的所有元素。

我必须将此用例通知 nokogiri 团队。

【问题讨论】:

    标签: ruby xml-parsing css-selectors nokogiri


    【解决方案1】:

    当您解析文档时,Nokogiri 试图理解它并且无法理解命名空间声明:

    puts xml_doc.errors
    

    返回:

    [#<Nokogiri::XML::SyntaxError: XML declaration allowed only at the start of the document>]
    

    这是因为 XML DECL:

    <?xml version="1.0"?>
    

    删除它可以解决这个问题。

    您访问节点属性的方式也不正确:

    result = xml_doc.css('ns1|el2[att]')
    result.each {|i| puts i}
    

    应该是:

    result = xml_doc.css('ns1|el2')
    result.each { |i| puts i['att'] }
    

    尝试访问带有命名空间的命名空间节点的属性很奇怪。我不记得曾经见过命名空间属性。 Nokogiri 似乎也不喜欢它:

    如果我运行这个:

    require 'nokogiri'
    
    xmlContent = %Q|
    <ns1:el1 xmlns:ns1="blabla">
      <ns1:el2 ns1:att="123">with namespace</ns1:el2 >
      <ns1:el2 att="noNameSpace">no namespace</ns1:el2 >
    </ns1:el1>|
    
    xml_doc = Nokogiri::XML(xmlContent)
    puts xml_doc.errors 
    
    puts "Searching for: 'att' attribute"
    result = xml_doc.css('ns1|el2')
    result.each { |i| puts i['att'] }
    
    puts "Searching for: 'ns1|att' attribute"
    result = xml_doc.css('ns1|el2')
    result.each { |i| puts i['ns1|att'] }
    

    我明白了:

    Searching for: 'att' attribute
    123
    noNameSpace
    Searching for: 'ns1|att' attribute
    

    result.first # => #<Nokogiri::XML::Element:0x8051e19c name="el2" namespace=#<Nokogiri::XML::Namespace:0x8051f344 prefix="ns1" href="blabla"> attributes=[#<Nokogiri::XML::Attr:0x8051e084 name="att" namespace=#<Nokogiri::XML::Namespace:0x8051f344 prefix="ns1" href="blabla"> value="123">] children=[#<Nokogiri::XML::Text:0x80519e30 "with namespace">]>
    result.first.keys # => ["att"]
    result.first.values # => ["123"]
    result.first['att'] # => "123"
    result.first['ns1|att'] # => nil
    result.first['ns1:att'] # => nil
    
    result.last # => #<Nokogiri::XML::Element:0x8051356c name="el2" namespace=#<Nokogiri::XML::Namespace:0x8051f344 prefix="ns1" href="blabla"> attributes=[#<Nokogiri::XML::Attr:0x805133a0 name="att" value="noNameSpace">] children=[#<Nokogiri::XML::Text:0x805122d4 "no namespace">]>
    result.last.keys # => ["att"]
    result.last.values # => ["noNameSpace"]
    result.last['att'] # => "noNameSpace"
    result.last['ns1|att'] # => nil
    result.last['ns1:att'] # => nil
    

    【讨论】:

    • 命名空间属性没有什么特别之处。 OP 使用的选择器语法看起来不错,但我不能说太多,因为我从未使用过 Nokogiri(而且我不是 Ruby 程序员)。
    • OP 应该把它交给 Nokogiri 开发团队。他们反应灵敏。
    • 感谢 Tin Man,我尝试使用 nokogiri 直接编辑 SSIS 包,并且 dtsx 文件包含命名空间属性。由于 nokogiri 不支持此功能,因此我必须改用常规字符串 gsub。
    • @kite,我添加了更多代码以使其更清楚地看到正在发生的事情。在 Nokogiri-Talk 邮件列表中提问。您可以在“Getting Help”页面上找到信息。
    猜你喜欢
    • 2020-04-24
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    相关资源
    最近更新 更多