这是一个效率问题,而不是故障排除。我有下面的代码片段:用XMLStarlet插入1000多个节点和属性 - 运行缓慢
# The -R flag restores malformed XML
xmlstarlet -q fo -R <<<"$xml_content" | \
# Delete xml_data
xmlstarlet ed -d "$xml_data" | \
# Delete index
xmlstarlet ed -d "$xml_index" | \
# Delete specific objects
xmlstarlet ed -d "$xml_nodes/objects" | \
# Append new node
xmlstarlet ed -s "$xml_nodes" -t elem -n subnode -v "Hello World" | \
# Add x attribute to node
xmlstarlet ed -i "($xml_nodes)[last()]" -t attr -n x -v "0" | \
# Add y attribute to node
xmlstarlet ed -i "($xml_nodes)[last()]" -t attr -n y -v "0" | \
# Add z attribute to node
xmlstarlet ed -i "($xml_nodes)[last()]" -t attr -n z -v "1" \
> "$output_file"
变量
$xml_content
包含内容的XML树和
节点从文件中解析大小为472.6 MB使用cat
命令。变量
$output_file
如其名称所示,包含输出文件的路径 。- 其余的变量只包含我想编辑的相应XPath。
根据这个简短的article这帮助想出这个代码,它表明:
这是一个有点ineffeciant因为XML文件进行解析,并写入两次。
在我的情况下,它被解析并写入两次以上(最终在loop
以上1000次)。
因此,采取上述脚本,该短片段的执行时间仅为4分7秒。
与文件大小一起假设过多,重复和低效也许管道就是为什么代码运行速度慢,越子节点我最终插入/删除最终会导致它更慢执行。
如果我通过重申自己或者提出一个陈旧而可能已经回答的话题来声音单调,我会提前道歉,但是,我真的很想了解xmlstarlet
如何详细处理大型XML文档。
UPDATE
正如他在回答之前声称@Cyrus:
这两个xmlstarlets应该做的工作:
xmlstarlet -q fo -R <<<"$xml_content" |\ xmlstarlet ed \ -d "$xml_data" \ -d "$xml_index" \ -d "$xml_nodes/objects" \ -s "$xml_nodes" -t elem -n subnode -v "Hello World" \ -i "($xml_nodes)[last()]" -t attr -n x -v "0" \ -i "($xml_nodes)[last()]" -t attr -n y -v "0" \ -i "($xml_nodes)[last()]" -t attr -n z -v "1" > "$output_file"
这产生的以下错误:
-:691.84: Attribute x redefined
-:691.84: Attribute z redefined
-:495981.9: xmlSAX2Characters: huge text node: out of memory
-:495981.9: Extra content at the end of the document
我真的不知道如何将这些错误在那里生产的,因为我改变了代码过于频繁测试各种情景和潜在的替代品,然而,这是我的伎俩:
xmlstarlet ed --omit-decl -L \
-d "$xml_data" \
-d "$xml_index" \
-d "$xml_nodes/objects" \
-s "$xml_nodes" -t elem -n subnode -v "Hello World" \
"$temp_xml_file"
xmlstarlet ed --omit-decl -L \
-i "($xml_nodes)[last()]" -t attr -n x -v "0" \
-i "($xml_nodes)[last()]" -t attr -n y -v "0" \
-i "($xml_nodes)[last()]" -t attr -n z -v "1" \
"$temp_xml_file"
关于所插入的实际data
,这是我在开头:
...
<node>
<subnode>A</subnode>
<subnode>B</subnode>
<objects>1</objects>
<objects>2</objects>
<objects>3</objects>
...
</node>
...
执行上述(分裂)的代码给了我什么,我想:
...
<node>
<subnode>A</subnode>
<subnode>B</subnode>
<subnode x="0" y="0" z="1">Hello World</subnode>
</node>
...
通过分裂它们的xmlstarlet
能够将attributes
插入到新创建的节点中,否则它将在创建--subnode
之前将它们添加到所选Xpath的last()
实例中。在某种程度上,这仍然是低效的,但是,代码现在不到一分钟。
下面的代码,
xmlstarlet ed --omit-decl -L \
-d "$xml_data" \
-d "$xml_index" \
-d "$xml_nodes/objects" \
-s "$xml_nodes" -t elem -n subnode -v "Hello World" \
-i "($xml_nodes)[last()]" -t attr -n x -v "0" \
-i "($xml_nodes)[last()]" -t attr -n y -v "0" \
-i "($xml_nodes)[last()]" -t attr -n z -v "1" \
"$temp_xml_file"
然而,使我这个:
...
<node>
<subnode>A</subnode>
<subnode x="0" y="0" z="1">B</subnode>
<subnode>Hello World</subnode>
</node>
...
通过加入xmlstarlets
成一个像这样post也@Cyrus回答,但也算是先加attributes
然后创建--subnode
,其中innerText
为Hello World
。
- 任何人都可以解释为什么这种奇怪的行为发生?
这是另一种reference其中规定:“每个编辑操作顺序执行”
上述文章解释正是我要找的,但我不能管理,使工作都在一个xmlstarlet ed \
。可替换地,我想:
- 在此answer更换
($xml_nodes)[last()]
与$xml_nodes[text() = 'Hello World']
- 使用
$prev
(或$xstar:prev
)作为参数-i
等。 [Examples] - 通过
-r
的temporary element name招重命名临时节点attr
添加
上述所有插入的--subnode
后,并保留新元素而不attributes
。
注意:我在OS X埃尔卡皮坦V上运行XMLStarlet 1.6.1 10.11.3
BONUS
正如我在开头提到的我希望用一个loop
像沿着这些线:
list="$(tr -d '\r' < $names)"
for name in $list; do
xmlstarlet ed --omit-decl -L \
-d "$xml_data" \
-d "$xml_index" \
-d "$xml_nodes/objects" \
-s "$xml_nodes" -t elem -n subnode -v "$name" \
-i "($xml_nodes)[last()]" -t attr -n x -v "0" \
-i "($xml_nodes)[last()]" -t attr -n y -v "0" \
-i "($xml_nodes)[last()]" -t attr -n z -v "1" \
"$temp_xml_file"
done
该$list
包含超过一千个不同的名称,需要分别添加它们的attributes
。每个属性的--value
也可能随着每个loop
而变化。鉴于上述模型:
什么是这样
loop
的最快,最准确的版本给出的属性被正确添加到相应的节点?在外部txt文件中创建节点列表并稍后将这些xml元素(在txt文件内)添加到另一个XML文件会更快吗?如果是,如何?也许用
sed
或grep
?
关于最后一个问题,我指的是像this。应该添加来自txt的xml
的节点必须是特定的,例如,至少可以选择XPath,因为我只想编辑某些节点。
注意:上述模型只是一个例子。实际的loop
将为每个loop
添加26 --subnodes
,并且每个--subnode
添加3或4个attr
。这就是为什么xmlstarlet
正确添加attr
而非其他元素很重要。他们必须按顺序添加。
我更新了我与例如输入/输出问题,就像你所说@Cyrus –