13

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

示例 XML 输入:

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

我想要的 CSV 输出:

Foo,
Bar,
4

8 回答 8

12

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

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

于 2008-08-27T05:48:46.433 回答
9

使用命令行 XSLT 处理器(例如xsltprocsaxonxalan)来解析 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>
于 2008-08-26T21:40:02.943 回答
7

XMLStarlet 是一个用于查询/编辑/检查/转换 XML 文档的命令行工具包(有关详细信息,请参阅XMLStarlet 命令行 XML 工具包

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

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

-m 表达式 -v value '' 包含文字 -n 换行符

因此,对于您的 xpath,xpath 表达式将是 //myel/@name ,它将提供两个属性值。

非常方便的工具。

于 2008-09-12T08:05:58.733 回答
6

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

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

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

于 2008-08-26T21:47:42.753 回答
2

这是一个小红宝石脚本,它完全按照您的问题要求(从名为“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'] }
于 2008-08-27T07:25:01.320 回答
1

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

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

它有它的缺陷,例如,如果没有严格考虑每个myel都在一行上,那么您必须首先“规范化”xml 文件(因此每个myel都在一个单独的行上)

于 2008-09-18T08:40:35.137 回答
1

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

<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
cat text.xml | tr -s "\"" " " | awk '{printf "%s,\n", $3}'
于 2014-01-21T06:12:50.897 回答
1

使用

xidel -s input.xml -e '//myel/concat(@name,",")'
于 2020-10-31T14:21:59.253 回答