我有一个XML文档,它具有默认名称空间和根目录上定义的另一个前缀:
<r xmlns="a://foo" xmlns:b="a://bar" x="y"><!-- content not using b:* --></r>
使用Nokogiri,我已经浏览了文档,并使用b
名称空间删除了元素和属性。现在我想修改文档,以便在输出时不具有b
名称空间,即
<r xmlns="a://foo" x="y"><!-- content not using b:* --></r>
什么不工作
如果我使用remove_namespaces!
,我甚至失去了默认的命名空间,这是我不想要的:
<r x="y"><!-- content not using b:* --></r>
我可以使用XPath选择名称空间,但Nokogiri::XML::Namespace
不继承Node
,也没有remove
方法:
doc.at('//namespace::*[name()="b"]')
#=> #<Nokogiri::XML::Namespace:0x8104118c prefix="b" href="a://bar">
doc.at('//namespace::*[name()="b"]').remove
#=> NoMethodError: undefined method `remove' for #<Nokogiri::XML::Namespace:0x81025acc prefix="b" href="a://bar">
doc.xpath('//namespace::*[name()="b"]').remove; puts doc
#=> <r xmlns="a://foo" xmlns:b="a://bar" x="y"><!-- content not using b:* --></r>
根元素没有将命名空间声明作为可以被删除的属性:
doc.root.attributes
#=> {"x"=>#<Nokogiri::XML::Attr:0x8103dba4 name="x" value="y">}
什么样的作品
由于文档很小,我将接受任何创建一个没有名称空间的文档新副本的解决方案,而不是改变现有的名称空间。
目前为止我得到的最好的解决方案是
doc.remove_namespaces!
doc.root.add_namespace(nil,'foo')
在Nokogiri中,您可以将文档canonicalize
,仅跳过名称空间声明,如下所示:
result = doc.canonicalize(nil,nil,1) do |o,_|
!o.is_a?(Nokogiri::XML::Namespace) || o.href!="a://bar"
end
返回一个字符串(不是一个新文档)。如果你想要一个新的文档,你可以doc2 = Nokogiri.XML(result)
.
请注意,虽然Nokogiri::XML::Node
也有canonicalize
方法,但它不接受块来决定是否保留项。你必须在文档本身调用这个。
第三个参数需要在规范化中包含注释。我不知道前两个选项做什么,除了运行时将分段故障,如果你传递一个1
第二个参数。
但是,这个答案也会从文档中去掉空白。我不会接受这个
你可以选择根元素并删除它的属性,像这样:
doc.css('r')[0].attributes['xmlns:b'].remove
引用你自己的答案之一:)
使用文档作为HTML,
irb(main):001:0> require 'nokogiri'
=> true
irb(main):002:0> doc = '<r xmlns="foo" xmlns:b="bar" x="y"><!-- content not using b:* --></r>'
=> "<r xmlns="foo" xmlns:b="bar" x="y"><!-- content not using b:* --></r>"
irb(main):004:0> xml = Nokogiri::HTML(doc)
=> #<Nokogiri::HTML::Document:0x3fe4544e6268 name="document" children=[#<Nokogiri::XML::DTD:0x3fe4544e3158 name="html">, #<Nokogiri::XML::Element:0x3fe4544e2834 name="html" children=[#<Nokogiri::XML::Element:0x3fe4544e2410 name="body" children=[#<Nokogiri::XML::Element:0x3fe4544e2050 name="r" attributes=[#<Nokogiri::XML::Attr:0x3fe4544df01c name="xmlns" value="foo">, #<Nokogiri::XML::Attr:0x3fe4544dfcec name="xmlns:b" value="bar">, #<Nokogiri::XML::Attr:0x3fe4544dfd00 name="x" value="y">] children=[#<Nokogiri::XML::Comment:0x3fe4544df418 " content not using b:* ">]>]>]>]>
irb(main):005:0> xml.to_s
=> "<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">n<html><body><r xmlns="foo" xmlns:b="bar" x="y"><!-- content not using b:* --></r></body></html>n"
irb(main):006:0> xml.css('r')[0].attributes['xmlns:b'].remove
=> #<Nokogiri::XML::Attr:0x3fe4544dfcec name="xmlns:b" value="bar">
irb(main):007:0> xml.to_s
=> "<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">n<html><body><r xmlns="foo" x="y"><!-- content not using b:* --></r></body></html>n"
irb(main):008:0>