1

我有一个 XML 文档:

<?xml version="1.0"?>
<installation id="ayfw-a">
</installation>

我正在向此文档添加一个子节点,如下所示:

data = Nokogiri::XML(IO.read('file')) { |doc| doc.noblanks }
new_record = Nokogiri::XML::Node.new('tag', data)
data.root.add_child(new_record)
File.open('file', 'w') { |dh_file| dh_file.write(data.to_xml(:indent => 4)) }

使用此代码,我在我的文件中得到了这个:

<?xml version="1.0"?>
<installation id="ayfw-a">
<tag/></installation>

在这里noblanks不起作用。但是,如果在插入新节点之前我的文件已经有一个子节点,则noblanks可以正常工作:

在插入新节点之前:

<?xml version="1.0"?>
<installation id="ayfw-a">
    <!---->
</installation>

插入新节点后:

<?xml version="1.0"?>
<installation id="ayfw-a">
    <!---->
    <tag/>
</installation>

所以,它看起来noblanks只有在它已经看到“模式”时才有效。如果我的 XML 还没有任何子级,有什么方法可以正确缩进它?


也许noblanks不是正确的选择,但由于某种原因,如果我已经在<installation>. 基本上我在添加子节点时目前拥有的是:

<?xml version="1.0"?>
<installation id="ayfw-a">
<tag/></installation>

我需要的是:

<?xml version="1.0"?>
<installation id="ayfw-a">
    <tag/>
</installation>

我添加的子节点必须是空的,为了简单起见,我隐藏了一些属性。

4

2 回答 2

0

你的两个例子令人困惑:它们都表现出完全相同的行为,但你说其中一个做了不同的事情。

据我所知,指定noblanks永远不会摆脱空节点:

xml.xml:

<?xml version="1.0"?>
<root>
  <installation id="ayfw-a"></installation>
  <dog></dog>
  <cat/>
</root>

.

require 'nokogiri'

data = Nokogiri::XML(IO.read('xml.xml')) { |doc| doc.noblanks }
puts data

--output:--
<?xml version="1.0"?>
<root>
  <installation id="ayfw-a"/>
  <dog/>
  <cat/>
</root>

我希望输出是:

<root>
  <installation id="ayfw-a"></installation>
</root>

当然,可怕的 Nokogiri 文档(典型的 Ruby)并没有定义什么是空白节点。显然,这样做的程度noblanks是像这样转换节点:

<dog></dog>

至:

<dog/>

啊,所以你的问题在于你的 XML 的漂亮打印。好的,我看到了和你一样的问题。让我向您展示如何提出您的问题:


我无法按照我想要的方式格式化我的 XML:

xml.xml:

<?xml version="1.0"?>
<installation id="ayfw-a">
</installation>

.

require 'nokogiri'

data = Nokogiri::XML(IO.read('xml.xml')) {|doc| doc.noblanks}
new_record = Nokogiri::XML::Node.new('tag', data)
data.root.add_child(new_record)
puts data.to_xml(indent: 4, indent_text: ".")

--output:--
<?xml version="1.0"?>
<installation id="ayfw-a">
<tag/></installation>

to_xml()方法似乎无法正常工作。我预计输出是:

<?xml version="1.0"?>
<installation id="ayfw-a">
....<tag/>
</installation>

但是,to_xml()当标签具有预先存在的子节点时,该方法会按照我想要的方式格式化输出:

xml.xml:

<?xml version="1.0"?>
<installation id="ayfw-a">
  <dog>Rover</dog>
</installation>

.

require 'nokogiri'

data = Nokogiri::XML(IO.read('xml.xml')) {|doc| doc.noblanks}
new_record = Nokogiri::XML::Node.new('tag', data)
data.root.add_child(new_record)
puts data.to_xml(indent: 4, indent_text: ".")

--output:--
<?xml version="1.0"?>
<installation id="ayfw-a">
....<dog>Rover</dog>
....<tag/>
</installation>

在第一种情况下,如何让 Nokogiri 按照我想要的方式格式化输出?


看起来 Nokogiri 没有一台非常好的漂亮打印机。似乎 REXML 有比 Nokogiri 更好的漂亮打印机:

xml.xml:

<?xml version="1.0"?>
<installation id="ayfw-a">
</installation>

.

require 'nokogiri'

data = Nokogiri::XML(IO.read('xml.xml')) {|doc| doc.noblanks}
new_record = Nokogiri::XML::Node.new('tag', data)
data.root.add_child(new_record)
puts data.to_xml(indent: 4, indent_text: ".")

require "rexml/document"

REXML::Document.new(data.to_xml).write(File.open("output.txt", "w"), indent_spaces = 4)


--output:--
<installation id="ayfw-a">
<tag/></installation>

$ cat output.txt
<?xml version='1.0'?>
<installation id='ayfw-a'>
    <tag/>
</installation>
于 2013-08-04T09:04:07.617 回答
-1

漂亮的打印 XML 并不能保证正确的 XML,它只是“漂亮”。Nokogiri 生成有效的 XML,这要重要得多。

如果您必须具有某种起始格式,请创建一个小模板供 Nokogiri 解析,然后在其上构建:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<?xml version="1.0"?>
<installation id="ayfw-a">
  <tag/>
</installation>
EOT

puts doc.to_xml

生成:

<?xml version="1.0"?>
<installation id="ayfw-a">
    <tag/>
</installation>

稍微调整一下代码可以让我设置起始root节点的 ID 和嵌入标签的名称:

require 'nokogiri'

ID = 'ayfw-a'
TAG = 'foo'

doc = Nokogiri::XML(<<EOT)
<?xml version="1.0"?>
<installation id="#{ ID }">
    <#{ TAG }/>
</installation>
EOT

puts doc.to_xml

哪个输出:

<?xml version="1.0"?>
<installation id="ayfw-a">
    <foo/>
</installation>

另一种写法是:

require 'nokogiri'

ID = 'ayfw-a'
TAG = 'foo'

doc = Nokogiri::XML(<<EOT)
<?xml version="1.0"?>
<installation>
    <tag/>
</installation>
EOT

doc.root['id'] = ID
doc.at('tag').name = TAG

puts doc.to_xml

哪个输出:

<?xml version="1.0"?>
<installation id="ayfw-a">
    <foo/>
</installation>

无论您做什么,它都能让您解决问题并提高工作效率。

于 2013-08-06T05:18:40.293 回答