为什么Nokogiri的to_xhtml从"name"创建新的"id"属性?



请考虑以下代码:

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. 为什么会这样?(这是在执行标准吗?
    我能找到的最接近的是这个规范,它描述了如何将idname属性与相同的值放在一起。
  3. 鉴于希望在可能<a name="foo">输入上使用 to_xhtml 方法,有没有办法避免这种情况?

出现此问题是因为我正在解析一些输入,我正在使用一个元素上的id属性和一个具有恰好冲突的name属性的单独元素进行解析。

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

在XML中,片段标识符的类型是ID,每个元素只能有一个类型为ID的属性。因此,在 XHTML 1.0 中,id 属性被定义为 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

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

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

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

相关内容

  • 没有找到相关文章

最新更新