這是一個效率問題,而不是故障排除。我有下面的代碼片段:用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 –