2015-06-11 283 views
1

您好我需要对这部分xml进行一些文本处理。 删除一些标签是没有问题的。我之前需要将汽车ID重命名为CAR_ID,并在TRIP标签内移动。更改XML结构

ie:MLStarlet Toolkit?

xmlstarlet somevariable

原始

<car> 
    <id>155028827</id> 
    <trip> 
     <id>1</id> 
     <date>1.1.1970</date> 
    </trip> 
    <trip> 
     <id>2</id> 
     <date>1.1.1970</date> 
    </trip> 
    </car> 

厚望结果

<trip> 
    <car_id>155028827</id> 
    <id>1</id> 
    <date>1.1.1970</date> 
</trip> 
<trip> 
    <car_id>155028827</id> 
    <id>2</id> 
    <date>1.1.1970</date> 
</trip> 
+0

你已经尝试过什么,失败的部分或未完成的行为是什么? – NeronLeVelu

回答

1

我想说

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传递给后者。

+0

你是最棒的。 thx很多,我不是程序员,“descendant :: node()[1]”听起来像来自火星的音乐:)。非XML的标准是没有问题的,我会准备插入到MySQL的XML。Thx再次。 –

+0

这些过滤器是[XPath](http://www.w3schools.com/xpath/)表达式; '后代'是[Xpath轴](http://www.w3schools.com/xpath/xpath_axes.asp)。处理XML时XPath是一个非常方便的工具(并且学习起来不是很困难),所以我鼓励您阅读它。 – Wintermute

+0

您可以使用'--root'或'-R'(如'xmlstarlet sel -R -t ...')将输出包装到单个节点中。 – npostavs