3

考虑以下代码:

require 'nokogiri' # v1.5.2
doc = Nokogiri.XML('<body><a name="foo">ick</a></body>')

puts doc.to_html
#=> <body><a name="foo">ick</a></body>

puts doc.to_xml
#=> <?xml version="1.0"?>
#=> <body>
#=>   <a name="foo">ick</a>
#=> </body>

 puts doc.to_xhtml
 #=> <body>
 #=>   <a name="foo" id="foo">ick</a>
 #=> </body>

id请注意已创建的新属性。

  1. 谁对此负责,Nokogiri 还是 libxml2?
  2. 为什么会出现这种情况?(这是强制执行标准吗?)
    我能找到的最接近的是这个规范,描述了如何anidnameattribute 设置为相同的值。
  3. 有什么办法可以避免这种情况,因为希望to_xhtml在可能有的输入上使用该方法<a name="foo">

出现此问题是因为我有一些输入,我正在解析一个元素上的属性和一个带有碰巧发生冲突id的属性的单独元素。name

4

2 回答 2

2

显然这是 libxml2 的一个特性。在http://www.w3.org/TR/xhtml1/#h-4.10我们发现:

在 XML 中,片段标识符是 type ,每个元素ID只能有一个 type 属性。ID因此,在 XHTML 1.0 中,该id属性被定义为 type ID。为了确保 XHTML 1.0 文档是结构良好的 XML 文档,XHTML 1.0 文档在为上面列出的元素定义片段标识符时必须使用该属性。id
[...]
请注意,在 XHTML 1.0 中,name这些元素的属性已被正式弃用,并将在 XHTML 的后续版本中删除。

我想出的最好的“解决方法”是:

# Destroy all <a name="..."> elements, replacing with children
# if another element with a conflicting id already exists in the document
doc.xpath('//a[@name][not(@id)][not(@href)]').each do |a|
  a.replace(a.children) if doc.at_css("##{a['name']}")
end
于 2012-04-20T20:20:04.890 回答
1

也许您可以id为这些元素添加一些其他值,以防止 libxml 添加自己的值。

doc.xpath('//a[@name and not(@id)]').each do |n|
  n['id'] = n['name'] + 'some_suffix'
end

(显然,您需要确定如何id为您的文档创建一个独特的价值)。

于 2012-04-20T21:23:04.797 回答