将XML标记值移动到其他标记

时间:2018-01-31 16:50:23

标签: xml bash

我正在尝试使用可以在bash中运行的命令创建一个简单的脚本,这将允许我获取XML文件的值并重新排列它们。拿这个样本文件:

<item1>
    <line>ASDF</line>
    <importantLine1>AAA</importantLine1>
    <importantLine2>BBB</importantLine2>
    <junkLine>CCC</junkLine>
    <importantLine3>DDD</importantLine3>
    <nest>
        <nestedLine>EEE</nestedLine>
    </nest>
</item1>
<item2>
    <line>ASDF</line>
    <importantLine1>AAA</importantLine1>
    <importantLine2>BBB</importantLine2>
    <junkLine>CCC</junkLine>
    <importantLine3>DDD</importantLine3>
    <nest>
        <nestedLine>EEE</nestedLine>
    </nest>
</item2>
<item3>
    <line>ASDF</line>
    <importantLine1>AAA</importantLine1>
    <importantLine2>BBB</importantLine2>
    <junkLine>CCC</junkLine>
    <importantLine3>DDD</importantLine3>
    <nest>
        <nestedLine>EEE</nestedLine>
    </nest>
</item3>

...

我想让输出看起来像这样,从一些标签移动值并将它们放在一起:

<item1>
    <line>ASDF</line>
    <importantLine2>DDD "AAA" BBB [EEE]</importantLine2>
    <junkLine>CCC</junkLine>
</item1>
<item2>
    <line>ASDF</line>
    <importantLine2>DDD "AAA" BBB [EEE]</importantLine2>
    <junkLine>CCC</junkLine>
</item2>
<item3>
    <line>ASDF</line>
    <importantLine2>DDD "AAA" BBB [EEE]</importantLine2>
    <junkLine>CCC</junkLine>
</item3>

如果有的话,我想学习如何改变价值观,而不仅仅是让它成为现实的答案。 “教一个人钓鱼......”

2 个答案:

答案 0 :(得分:1)

使用package xsltproc这可以通过XSLT文件实现。元素的顺序并不完全正确,但没有任何标准,这就是它的好处。如有必要,可以使用<xsl:sort ...>左右订购输出。

您必须将所有item???元素放在一个根元素中才能使此解决方案正常工作。

<强> reorder.xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="*[starts-with(local-name(),'item')]">
    <xsl:copy>
      <xsl:copy-of select="line" /> 
      <importantLine2>
      <xsl:for-each select="*[starts-with(local-name(),'importantLine')]">
        <xsl:value-of select="concat(text(),' ')"/>     
      </xsl:for-each>
      <xsl:for-each select="nest/nestedLine">
        <xsl:text>[</xsl:text><xsl:value-of select="concat(text(),' ')"/><xsl:text>]</xsl:text>
      </xsl:for-each>
      </importantLine2>
      <xsl:copy-of select="junkLine" /> 
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

xsltproc

一起使用
xsltproc reorder.xslt your.xml

输出为:

<item1>
    <line>ASDF</line>
    <importantLine2>AAA BBB DDD [EEE ]</importantLine2>
    <junkLine>CCC</junkLine>
</item1>
<item2>
    <line>ASDF</line>
    <importantLine2>AAA BBB DDD [EEE ]</importantLine2>
    <junkLine>CCC</junkLine>
</item2>
<item3>
    <line>ASDF</line>
    <importantLine2>AAA BBB DDD [EEE ]</importantLine2>
    <junkLine>CCC</junkLine>
</item3>

答案 1 :(得分:0)

xmlstarlet 解决方案:

假设使用&#34; root&#34; (主)节点的有效XML文档:

xmlstarlet ed -O -u "//importantLine2" \
-x 'concat(parent::*/importantLine3, " ", parent::*/importantLine1, " ", . , 
   " [", parent::*//nestedLine, "]")' \
-d '//importantLine1 | //importantLine3 | //nest' xmlfile
  • ed - 编辑模式
  • -O - 省略XML声明(<?xml ...?>)
  • -u - 更新行动;完整签名:-u or --update <xpath> -v (--value) <value> -x (--expr) <xpath>
  • -d - 删除操作;完整签名:-d or --delete <xpath>

输出:

<root>
  <item1>
    <line>ASDF</line>
    <importantLine2>DDD AAA BBB [EEE]</importantLine2>
    <junkLine>CCC</junkLine>
  </item1>
  <item2>
    <line>ASDF</line>
    <importantLine2>DDD AAA BBB [EEE]</importantLine2>
    <junkLine>CCC</junkLine>
  </item2>
  <item3>
    <line>ASDF</line>
    <importantLine2>DDD AAA BBB [EEE]</importantLine2>
    <junkLine>CCC</junkLine>
  </item3>
</root>