替换BASH中的xml标记

时间:2013-06-06 19:05:17

标签: bash sed

我有大量的xml文档,其中包含大量不同的标记。我需要更改表单<foo>的所有标记,并将其转换为<field name="foo">形式的标记,其方式也会忽略给定标记的属性。也就是说,<foo id="bar">形式的标记也应更改为标记<field name="foo">

为了让这种转变发挥作用,我还需要区分<foo></foo>,因为</foo>必须转到</field>

我在bash脚本中玩过sed,但无济于事。

2 个答案:

答案 0 :(得分:3)

虽然sed并不适合这项任务(参见评论;进一步阅读:常规,无上下文语法和xml),但它可以投入使用。试试这个单行:

sed -e 's/<\([^>\/\ ]*\)[^>]*>/<field name=\"\1\">/g' -e 's/<field name=\"\">/<\/field>/g' file 

首先,它会用</field>替换所有结束标记,然后用<field name="firstStoredWord">

替换每个开放标记的第一个单词

此解决方案打印标准输出上的所有内容。如果要在处理时直接将其替换为文件,请尝试

sed -i -e 's/<\([^>\/\ ]*\)[^>]*>/<field name=\"\1\">/g' -e 's/<field name=\"\">/<\/field>/g' file

这来自

<html>
<person> 
but <person name="bob"> and <person name="tom"> would both become
</person>

<field name="html">
<field name="person"> 
but <field name="person"> and <field name="person"> would both become
</field>

答案 1 :(得分:0)

Sed是错误的工具 - 简单的XSL Transform可以更可靠地完成这项工作:

<?xml version="1.0"?>

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

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

   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()" />
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

请注意,与sed不同,它可以处理短空元素,标记内的换行符(例如,由某些工具生成),以及几乎任何格式良好的XML。这是我的测试文件:

<?xml version="1.0"?>
<doc>
  <section>
    <foo>Plain foo, simple content</foo>
  </section>
  <foo attr="0">Foo with attr, with content
    <bar/>
    <foo attr="shorttag"/>
  </foo>
  <foo
    attr="1"
  >multiline</foo
  >
  <![CDATA[We mustn't transform <foo> in here!]]>
</doc>

由上述(使用xsltproc 16970175.xslt 16970175.xml)转换为:

<?xml version="1.0"?>
<doc>
  <section>
    <field name="foo">Plain foo, simple content</field>
  </section>
  <field name="foo">Foo with attr, with content
    <bar/>
    <field name="foo"/>
  </field>
  <field name="foo">multiline</field>
  We mustn't transform &lt;foo&gt; in here!
</doc>