Ruby 从文档中删除特定命名空间

Ruby 从文档中删除特定命名空间,ruby,xml,nokogiri,Ruby,Xml,Nokogiri,我有一个XML文档,在根目录上定义了一个默认名称空间和另一个前缀: 使用我已经浏览了文档,并使用b名称空间删除了元素和属性。现在我想修改文档,以便在输出时它没有b名称空间,即 什么不起作用 如果使用,我甚至会丢失默认名称空间,这是我不想要的: 我可以使用XPath选择命名空间,但Nokogiri::XML::namespace不会从节点继承,也没有remove方法: doc.at'//命名空间::*[name=b]' => doc.at'//命名空间::*[name=b]'。删除 =>NoMe

我有一个XML文档,在根目录上定义了一个默认名称空间和另一个前缀:

使用我已经浏览了文档,并使用b名称空间删除了元素和属性。现在我想修改文档,以便在输出时它没有b名称空间,即

什么不起作用 如果使用,我甚至会丢失默认名称空间,这是我不想要的:

我可以使用XPath选择命名空间,但Nokogiri::XML::namespace不会从节点继承,也没有remove方法:

doc.at'//命名空间::*[name=b]' => doc.at'//命名空间::*[name=b]'。删除 =>NoMethodError:未定义的方法“删除” doc.xpath'//命名空间::*[name=b]'。删除;放博士 => 根元素未将命名空间声明作为可删除的属性包括在内:

doc.root.attributes =>{x=>} 什么样的作品 由于文档很小,我将接受任何不使用名称空间而创建文档新副本的解决方案,而不是修改现有副本

到目前为止,我得到的最好的解决办法是

doc.remove_名称空间! doc.root.add_namespacenil,'foo'
…但此核心选项还将删除根的子代上的任何名称空间,这是不可取的。

您可以选择根元素并删除其属性,如下所示:

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>
在Nokogiri中,您可以跳过名称空间声明,如下所示:

result = doc.canonicalize(nil,nil,1) do |o,_|
  !o.is_a?(Nokogiri::XML::Namespace) || o.href!="a://bar"
end
这将返回一个字符串,而不是新文档。如果需要新文档,可以使用doc2=Nokogiri.XMLresult

注意,虽然Nokogiri::XML::Node也有一个规范化方法,但它不接受块来决定是否保留项。您必须在文档本身上调用它

第三个参数是在规范化中包含注释所必需的。我知道前两个选项的作用,但运行时会


然而,这个答案也去除了文档中的空白。我不会接受此操作。

是否仅从根元素中删除文本xmlns:b=bar?为什么不使用regex?@emaillenin是的,我只想删除它。对结果进行文本修改是一个选项,尽管a需要序列化、mung,然后重新解析文档,b。但是不太可能,例如,该字符串可能是根元素上另一个属性的值。您测试过这个吗?这对我不起作用。这些属性在我的安装中不包括命名空间声明。另外:doc.at'r'或doc.root稍微简单一点。是的,但我使用Nokogiri::HTML来初始化;而不是有趣。鉴于HTML对内容的影响,我不能接受这一点,但我也不会投反对票。