有时我需要从 XML 文件中快速提取一些任意数据以放入 CSV 格式。在 Unix 终端中执行此操作的最佳实践是什么?我会喜欢一些代码示例,例如如何解决以下问题?
示例 XML 输入:
<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
我想要的 CSV 输出:
Foo,
Bar,
彼得的答案是正确的,但它会输出一个尾随换行符。
<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>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
只需运行例如
xsltproc stylesheet.xsl source.xml
将 CSV 结果生成到标准输出中。
使用命令行 XSLT 处理器(例如xsltproc、saxon或xalan)来解析 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> </xsl:text>
</xsl:template>
</xsl:stylesheet>
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 ,它将提供两个属性值。
非常方便的工具。
如果您只想要任何元素的名称属性,这里有一个快速但不完整的解决方案。
(您的示例文本在文件示例中)
grep "名称" 示例 | 剪切 -d"\"" -f2,2 | xargs -I{} echo "{},"
这是一个小红宝石脚本,它完全按照您的问题要求(从名为“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'] }
您的测试文件在 test.xml 中。
sed -n 's/^\s`*`<myel\s`*`name="\([^"]`*`\)".`*`$/\1,/p' test.xml
它有它的缺陷,例如,如果没有严格考虑每个myel都在一行上,那么您必须首先“规范化”xml 文件(因此每个myel都在一个单独的行上)
回答原始问题,假设 xml 文件是“test.xml”,其中包含:
<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
cat text.xml | tr -s "\"" " " | awk '{printf "%s,\n", $3}'
使用xidel:
xidel -s input.xml -e '//myel/concat(@name,",")'