如何在树中的xml文件中移动元素

时间:2016-07-22 12:42:48

标签: xml awk sed xmlstarlet

我有以下格式的xml文件:

<results>
 <sequence-name>name1</sequence-name>
 <repetitions>
  <window>
   <key1>1</key1>
  </window>
 </repetitions>
 <sequence-name>name2</sequence-name>
 <repetitions>
  <window>
   <key1>4</key1>
  </window>
  </repetitions>
</results>

我想移动元素sequence-name,使其成为window内的第一个元素,因此输出应如下所示:

<results>    
 <repetitions>
  <window>
   <sequence-name>name1</sequence-name>
   <key1>1</key1>
  </window>
 </repetitions>    
 <repetitions>
  <window>
   <sequence-name>name2</sequence-name>
   <key1>4</key1>
  </window>
 </repetitions>
</results>

我尝试使用grep生成两个文件,一个只包含<sequence-name>的行,另一个包含所有其他行。但我无法弄清楚如何将包含<sequence-name>的行插回到我想要的位置。我猜测有一个使用sed/aw k的解决方案。我也很高兴使用xmlstarlet等工具。

3 个答案:

答案 0 :(得分:2)

以下样式表可以解决这个问题:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/ | node()">
  <xsl:copy>
    <xsl:apply-templates select="node()[not(self::sequence-name)]" />
  </xsl:copy>
</xsl:template>

<xsl:template match="window">
  <xsl:copy>
    <xsl:copy-of select="preceding::sequence-name[1]" />
    <xsl:apply-templates select="key1"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

您可以使用xsltproc stylesheet dataxmlstarlet tr stylesheet data来应用它。

答案 1 :(得分:1)

如果您的文件总是格式良好且在xmlstarlet中非常重要:

$ awk '/<sequence-name>/{s=$0;next} {print} /<window>/{print s}' file
<results>
 <repetitions>
  <window>
 <sequence-name>name1</sequence-name>
   <key1>1</key1>
  </window>
 </repetitions>
 <repetitions>
  <window>
 <sequence-name>name2</sequence-name>
   <key1>4</key1>
  </window>
  </repetitions>
</results>

如果你关心缩进:

$ awk '/<sequence-name>/{s=$0; next} {print} /<window>/{indent=$0; sub(/[^[:space:]].*/," ",indent); sub(/^[[:space:]]*/,indent,s); print s}' file
<results>
 <repetitions>
  <window>
   <sequence-name>name1</sequence-name>
   <key1>1</key1>
  </window>
 </repetitions>
 <repetitions>
  <window>
   <sequence-name>name2</sequence-name>
   <key1>4</key1>
  </window>
  </repetitions>
</results>

答案 2 :(得分:0)

另一种方法,只使用sed:

$ sed '/<sequence-name>/{s/^/  /; h; d;}; /<window>/G;' file
<results>
 <repetitions>
  <window>
   <sequence-name>name1</sequence-name>
   <key1>1</key1>
  </window>
 </repetitions>
 <repetitions>
  <window>
   <sequence-name>name2</sequence-name>
   <key1>4</key1>
  </window>
  </repetitions>
</results>