使用unix终端解析XML

时间:2020-03-05 18:43:32  来源:igfitidea点击:

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

XML输入示例:

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

我想要的CSV输出:

Foo,
Bar,

解决方案

回答

使用xsltproc,saxon或者xalan等命令行XSLT处理器来解析XML并生成CSV。这是一个示例,情况是样式表:

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

回答

如果只需要任何元素的名称属性,这是一种快速但不完整的解决方案。

(示例文本在文件示例中)

grep "name" example | cut -d"\"" -f2,2
  | xargs -I{} echo "{},"

回答

彼得的答案是正确的,但它输出尾随换行符。

<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结果生成为标准输出。

回答

这是一个小红宝石脚本,它完全满足问题要求(从名为" 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'] }

回答

XMLStarlet是用于查询/编辑/检查/转换的命令行工具包
XML文档(有关更多信息,请参见http://xmlstar.sourceforge.net/)

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

猫file.xml | xml sel -t -m'xpathExpression'-v'elemName''文字'-v'elname'-n
-m表达式
-v值
包括文字
-n换行符

因此,对于xpath,xpath表达式为// myel / @ name
这将提供两个属性值。

非常方便的工具。

高温超导

回答

测试文件在test.xml中。

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

它有一个陷阱,例如,如果不严格考虑每个myel在一行上,则必须首先"标准化" xml文件(因此每个myel在单独的一行上)