提问人:Mattias 提问时间:8/27/2008 最后编辑:Martin BrisiakMattias 更新时间:12/7/2022 访问量:50177
使用 unix 终端解析 XML
Parsing XML using unix terminal
问:
有时我需要从XML文件快速提取一些任意数据,以放入CSV格式。在 Unix 终端中执行此操作的最佳实践是什么?我想要一些代码示例,例如,如何解决以下问题?
XML 输入示例:
<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
我想要的 CSV 输出:
Foo,
Bar,
答:
使用命令行 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>
如果您只想要任何元素的名称属性,这里有一个快速但不完整的解决方案。
(您的示例文本在文件示例中)
grep “name” 示例 |切 -d“\”“ -f2,2 |xargs -I{} 回显 “{},”
Peter 的答案是正确的,但它输出的是尾随换行符。
<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 结果生成为标准输出。
这里有一个小的 ruby 脚本,它完全按照你的问题要求执行(从名为“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 文档(有关详细信息,请参阅 XMLStarlet 命令行 XML 工具包)
无需写入文件,只需将文件通过管道传输到 xmlstarlet 并应用 xpath 过滤器即可。
cat file.xml | xml sel -t -m 'xpathExpression' -v 'elemName' 'literal' -v 'elname' -n
-m 表达式 -v 值 '' 包含文字 -n 换行符
因此,对于您的 xpath,xpath 表达式将是 //myel/@name 这将提供两个属性值。
非常方便的工具。
您的测试文件位于 中。test.xml
sed -n 's/^\s*<myel\s*name="\([^"]*\)".*$/\1,/p' test.xml
它有其陷阱;例如,如果没有严格规定每个文件都在一行上,则必须首先“规范化”XML文件(因此每个文件都在单独的行上)。myel
myel
评论
sed
\s
回答原始问题,假设 xml 文件是“test.xml”,其中包含:
<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
tr -s "\"" " " < text.xml | awk '{printf "%s,\n", $3}'
使用 xidel:
xidel -s input.xml -e '//myel/concat(@name,",")'
yq 可用于 XML 解析。
它是一个轻量级且可移植的命令行 YAML 处理器,也可以处理 XML。 语法类似于 jq
输入
<root>
<myel name="Foo" />
<myel name="Bar">
<mysubel>stairway to heaven</mysubel>
</myel>
</root>
使用示例1
yq e '.root.myel.0.+name' $INPUT
(版本 >= 4.30:yq e '.root.myel.0.+@name' $INPUT
)
Foo
使用示例2
yq
有一个很好的内置功能,使 XML 易于 grep
yq --input-format xml --output-format props $INPUT
root.myel.0.+name = Foo
root.myel.1.+name = Bar
root.myel.1.mysubel = stairway to heaven
使用示例 3
yq
还可以将 XML 输入转换为 JSON 或 YAML
yq --input-format xml --output-format json $INPUT
{
"root": {
"myel": [
{
"+name": "Foo"
},
{
"+name": "Bar",
"mysubel": "stairway to heaven"
}
]
}
}
yq --input-format xml $FILE
(YAML
是默认格式)
root:
myel:
- +name: Foo
- +name: Bar
mysubel: stairway to heaven
上一个:解析,我在哪里可以了解它
评论