Nokogiri:在字段名中用`?`创建字符串的xml

时间:2013-03-20 21:07:34

标签: ruby-on-rails ruby nokogiri

控制器响应包括“规范”?字段:

r = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash type=\"array\">\n  <item><spec? type=\"boolean\">false</spec?>\n </item>\n  <hash>\n"

尝试使用Nokogiri.xml(r)从中创建xml时,按字面意思接收:

<?xml version="1.0" encoding="UTF-8"?>
<hash type="array">
  <item><spec type=" type=&quot;boolean&quot;&gt;false/spec">
 </spec>item&gt;
  <hash>
</hash></item></hash>

这是奇怪的事情;

我的问题是: 是否可以使用Nokogiri从字符串创建xml,在?阶段解析或删除Nokogiri.XML()和其他非xml-standart字符?

可取的结果:

Nokogiri.xml(r) do |config|
 config.maybe_some_configs?
end #=>
    <?xml version="1.0" encoding="UTF-8"?>
    <hash type="array">
      <item><spec type="boolean">false</spec></item>       
    </hash>

1 个答案:

答案 0 :(得分:1)

将字符串解析为XML DOM的正确方法是Nokogiri::XMLNokogiri.XMLNokogiri::XML.parse,但不使用xml

此外,XML标记不能包含?。有关详细信息,请参阅the spec。您将不得不深入研究“名称和标记”部分并解码十六进制字符描述以确定允许的字符范围,但提示?是字符代码0x3f

这导致r中的XML无效:

<?xml version="1.0" encoding="UTF-8"?>
<hash type="array">
  <item><spec? type="boolean">false</spec?>
 </item>
  <hash>

解析时会导致:

irb(main):012:0> doc = Nokogiri::XML(r)
#<Nokogiri::XML::Document:0x80c8014c name="document" children=[#<Nokogiri::XML::Element:0x80c7399c name="hash" attributes=[#<Nokogiri::XML::Attr:0x80c733e8 name="type" value="array">] children=[#<Nokogiri::XML::Text:0x80c6e26c "\n  ">, #<Nokogiri::XML::Element:0x80c6df60 name="item" children=[#<Nokogiri::XML::Element:0x80c6d970 name="spec">, #<Nokogiri::XML::Text:0x80c6d09c "? type=\"boolean\">false">]>, #<Nokogiri::XML::Text:0x80c6ca34 "?>\n ">]>]>
irb(main):013:0> doc.errors
[
    [0] #<Nokogiri::XML::SyntaxError: error parsing attribute name>,
    [1] #<Nokogiri::XML::SyntaxError: attributes construct error>,
    [2] #<Nokogiri::XML::SyntaxError: Couldn't find end of Start Tag spec line 3>,
    [3] #<Nokogiri::XML::SyntaxError: expected '>'>,
    [4] #<Nokogiri::XML::SyntaxError: Opening and ending tag mismatch: item line 3 and spec>,
    [5] #<Nokogiri::XML::SyntaxError: Opening and ending tag mismatch: hash line 2 and item>,
    [6] #<Nokogiri::XML::SyntaxError: Extra content at the end of the document>
]

因此,Nokogiri不得不在DOM中进行一些修复以尝试理解它。生成的XML看起来像:

irb(main):014:0> puts doc.to_xml
<?xml version="1.0" encoding="UTF-8"?>
<hash type="array">
  <item><spec/>? type="boolean"&gt;false</item>?&gt;
 </hash>

修复它的方法是给Nokogiri 有效的 XML。如果你控制它,要么修复XML的来源,要么在将它传递给Nokogiri之前修复字符串中的问题。

根据其定义,XML是一种严格的格式,Nokogiri对此表示尊重,并且尽量友好,使您可以检查errors以查看其empty?。如果不是,赔率很高你不应该继续使用源,直到你确定了问题并修复了解决问题的原因。有时问题是相当温和的,你可以忽略它,但在任何一种情况下你都应该至少知道它。

在Nokogiri认为并不困难之前预先按摩数据:

doc = Nokogiri::XML(r.gsub('spec?', 'spec'))

irb(main):024:0> puts doc.to_xml
<?xml version="1.0" encoding="UTF-8"?>
<hash type="array">
  <item><spec type="boolean">false</spec>
 </item>
  <hash>
</hash></hash>
nil
irb(main):025:0> doc.errors
[
    [0] #<Nokogiri::XML::SyntaxError: Premature end of data in tag hash line 5>,
    [1] #<Nokogiri::XML::SyntaxError: Premature end of data in tag hash line 2>
]

这是一个开始,但不是试图完全解决它。我教你钓鱼,而不是分发鱼。