2012-01-05 45 views
0

我的问题不同于“How can I get the values of attributes with namespace, using Nokogiri?”。如何使用“css”查询包含attributeNameA和namespaceB的元素?

我的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-3365636引入nokogiri不支持查询直接命名空间中的属性的XML元素。

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

我将不得不通知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 
+0

有什么特别的命名空间属性。 OP使用的选择器语法看起来很好,但由于我从未使用过Nokogiri(而且我不是Ruby程序员),所以我不能说很多其他的东西。 – BoltClock 2012-01-05 10:32:33

+0

OP应该把这个交给Nokogiri开发团队。他们非常敏感。 – 2012-01-05 16:24:18

+0

感谢Tin Man,我试图直接用nokogiri编辑SSIS包,并且dtsx文件包含名称空间属性。由于nokogiri不支持这个功能,我必须使用常规字符串gsub。 – kite 2012-01-06 07:12:18

相关问题