我想说
xmlstarlet ed -i '/car/trip/descendant::node()[1]' -t elem -n car_id -u '/car/trip/car_id' -x 'ancestor::node()["car"]/id/text()' filename.xml | xmlstarlet sel -t -c '/car/trip'
这分为两个部分:
xmlstarlet ed \
-i '/car/trip/descendant::node()[1]' -t elem -n car_id \
-u '/car/trip/car_id' -x 'ancestor::node()["car"]/id/text()' \
filename.xml
和
xmlstarlet sel -t -c '/car/trip'
第一种是xmlstarlet ed
命令,这意味着XML进去,被编辑时,和编辑XML熄灭。该编辑是
-i '/car/trip/descendant::node()[1]' -t elem -n car_id
这将插入每个/car/trip
节点的第一传人之前car_id
,并
-u '/car/trip/car_id' -x 'ancestor::node()["car"]/id/text()'
所有/car/trip/car_id
节点的值设置为文本id
子节点的car
祖先的内节点。仅此一点就产生
<?xml version="1.0"?>
<car>
<id>155028827</id>
<trip>
<car_id>1550288271</car_id>
<id>1</id>
<date>1.1.1970</date>
</trip>
<trip>
<car_id>1550288272</car_id>
<id>2</id>
<date>1.1.1970</date>
</trip>
</car>
其然后通过
xmlstarlet sel -t -c '/car/trip'
此选择(和打印)该XML数据的/car/trip
节点管道,产生
<trip>
<car_id>1550288271</car_id>
<id>1</id>
<date>1.1.1970</date>
</trip><trip>
<car_id>1550288272</car_id>
<id>2</id>
<date>1.1.1970</date>
</trip>
你可以,如果格式化惹恼你,使用
xmlstarlet sel -t -c '/car/trip | /car/text()'
保留标签之间的空白(并获得更易读的格式化输出);随着这种变化,输出是
<trip>
<car_id>1550288271</car_id>
<id>1</id>
<date>1.1.1970</date>
</trip>
<trip>
<car_id>1550288272</car_id>
<id>2</id>
<date>1.1.1970</date>
</trip>
......在顶部有两个空白行;它们是/car/id
节点前后的换行符。不幸的是,输出数据不再是有效的XML,所以我们不能通过一个XML漂亮的打印机(这是我真正想做的)来管理它。由于我怀疑它会嵌入到更多的XML中(因此它可以被正确解析),如果格式很重要,我的建议是首先将其嵌入,然后通过一个漂亮的打印机将整个XML传递给后者。
你已经尝试过什么,失败的部分或未完成的行为是什么? – NeronLeVelu