【问题标题】:Parsing XML using unix terminal使用 unix 终端解析 XML
【发布时间】:2010-09-06 22:32:08
【问题描述】:

有时我需要从 XML 文件中快速提取一些任意数据以放入 CSV 格式。在 Unix 终端中执行此操作的最佳实践是什么?我喜欢一些代码示例,例如如何解决以下问题?

示例 XML 输入:

<root>
    <myel name="Foo" />
    <myel name="Bar" />
</root>

我想要的 CSV 输出:

Foo,
Bar,

【问题讨论】:

    标签: xml unix parsing shell csv


    【解决方案1】:

    Peter's answer 是正确的,但它会输出一个尾随换行符。

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="text"/>
      <xsl:template match="root">
        <xsl:for-each select="myel">
          <xsl:value-of select="@name"/>
          <xsl:text>,</xsl:text>
          <xsl:if test="not(position() = last())">
            <xsl:text>&#xA;</xsl:text>
          </xsl:if>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    只需运行例如

    xsltproc stylesheet.xsl source.xml
    

    将 CSV 结果生成到标准输出中。

    【讨论】:

      【解决方案2】:

      使用命令行 XSLT 处理器(例如 xsltprocsaxonxalan)解析 XML 并生成 CSV。这是an example,对您来说就是样式表:

      <?xml version="1.0" encoding="ISO-8859-1"?>
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:output method="text"/>
      
          <xsl:template match="root">
              <xsl:apply-templates select="myel"/>
          </xsl:template>
      
          <xsl:template match="myel">
              <xsl:for-each select="@*">
                  <xsl:value-of select="."/>
                  <xsl:value-of select="','"/>
              </xsl:for-each>
              <xsl:text>&#10;</xsl:text>
          </xsl:template> 
      </xsl:stylesheet>
      

      【讨论】:

        【解决方案3】:

        XMLStarlet 是一个用于查询/编辑/检查/转换的命令行工具包 XML 文档(更多信息,请参阅XMLStarlet Command Line XML Toolkit

        没有要写入的文件,只需将文件通过管道传输到 xmlstarlet 并应用 xpath 过滤器。

        cat file.xml | xml sel -t -m 'xpathExpression' -v 'elemName' 'literal' -v 'elname' -n
        

        -m 表达式 -v 值 '' 包括文字 -n 换行

        所以对于您的 xpath,xpath 表达式将是 //myel/@name 这将提供两个属性值。

        非常方便的工具。

        【讨论】:

          【解决方案4】:

          如果您只想要任何元素的名称属性,这里有一个快速但不完整的解决方案。

          (您的示例文本在文件 example 中)

          grep "名称" 示例 |剪切 -d"\"" -f2,2 | xargs -I{} echo "{},"

          【讨论】:

            【解决方案5】:

            这是一个小红宝石脚本,完全按照您的问题要求执行(从名为“myel”的元素中提取一个名为“name”的属性)。应该很容易概括

            #!/usr/bin/ruby -w
            
            require 'rexml/document'
            
            xml = REXML::Document.new(File.open(ARGV[0].to_s))
            xml.elements.each("//myel") { |el| puts "#{el.attributes['name']}," if el.attributes['name'] }
            

            【讨论】:

              【解决方案6】:

              您的测试文件在 test.xml 中。

              sed -n 's/^\s`*`&lt;myel\s`*`name="\([^"]`*`\)".`*`$/\1,/p' test.xml
              

              它有它的缺陷,例如,如果不是严格地考虑到每个 myel 都在一行上,那么你必须首先“规范化”xml 文件(所以每个 myel > 在单独的一行上)

              【讨论】:

                【解决方案7】:

                回答原始问题,假设xml文件是“test.xml”,其中包含:

                <root>
                <myel name="Foo" />
                <myel name="Bar" />
                </root>
                
                cat text.xml | tr -s "\"" " " | awk '{printf "%s,\n", $3}'
                

                【讨论】:

                  【解决方案8】:

                  使用:

                  xidel -s input.xml -e '//myel/concat(@name,",")'
                  

                  【讨论】:

                    猜你喜欢
                    • 2015-04-28
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-01-14
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-05-19
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多