Replace 更改XML结构

Replace 更改XML结构,replace,sed,grep,xmlstarlet,Replace,Sed,Grep,Xmlstarlet,嗨,我需要对这部分xml进行一些文本操作。 删除一些标记没有问题。在此之前,我需要将车号重命名为car_ID,并移动到行程标签内 ie:MLStarlet工具包 xmlstarlet变量 原创的 <car> <id>155028827</id> <trip> <id>1</id> <date>1.1.1970</date> </trip>

嗨,我需要对这部分xml进行一些文本操作。 删除一些标记没有问题。在此之前,我需要将车号重命名为car_ID,并移动到行程标签内

ie:MLStarlet工具包

xmlstarlet变量

原创的

  <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>

155028827
1.
1.1.1970
2.
1.1.1970
期望结果

<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>

155028827
1.
1.1.1970
155028827
2.
1.1.1970
我想说

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 ed
命令,这意味着XML进入、编辑,编辑后的XML退出。编辑是

   -i '/car/trip/descendant::node()[1]' -t elem -n car_id
在每个
/car/trip
节点的第一个子节点之前插入
car\u id
,以及

   -u '/car/trip/car_id' -x 'ancestor::node()["car"]/id/text()'
它将所有
/car/trip/car\u id
节点的值设置为其
car
祖先节点的
id
子节点内的文本。仅此一点就产生了

<?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>
这将选择(并打印)此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>
保留标记之间的空白(并获得更易于阅读的格式化输出);通过此更改,输出是

  <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>

1550288271
1.
1.1.1970
1550288272
2.
1.1.1970

…顶部还有两行空白;它们是
/car/id
节点前后的换行符。不幸的是,输出数据不再是有效的XML,因此我们不能通过XML漂亮的打印机(这正是我真正想做的)。由于我怀疑这将被嵌入到进一步的XML中(以便正确解析),因此,如果格式化很重要,我的建议是先嵌入这一点,然后通过漂亮的打印机将整个XML传输。

您已经尝试了什么,失败的部分或未解决的行为是什么?您是最好的。thx很多,我不是程序员,“后代::节点()[1]”对我来说就像来自火星的音乐:)。非xml标准没有问题,我将准备xml以插入mysql。再次使用Thx。这些过滤器是表达式<代码>子体是一个。XPath在处理XML时是一个非常方便的工具(学习起来并不困难),因此我鼓励您仔细阅读。您可以使用
--root
-R
(如
xmlstarlet sel-R-t…
)将输出打包到单个节点中。
<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>