2008-08-26 63 views
11

有時我需要從XML文件中快速提取一些任意數據以將其轉換爲CSV格式。在Unix終端上做這件事的最佳做法是什麼?我會喜歡一些代碼示例,所以例如我怎樣才能解決以下問題?使用unix終端解析XML

示例XML輸入:

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

我期望CSV輸出:

Foo, 
Bar, 

回答

5

如果你只是想任何元素的name屬性,這裏是一個快速但不完整的解決方案。

(例如您的文字是在文件例如

grep的 「名」 的例子|切-d 「\」」 -f2,2 | xargs的-I {}回聲 「{}」

9

使用命令行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> 
11

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結果到標準輸出。

1

這裏有一個小的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'] } 
6

XMLStarlet是一個命令行工具來查詢/編輯/檢查/變換 XML文件(有關詳細信息,請參閱http://xmlstar.sourceforge.net/

沒有文件寫的,只是管你的文件xmlstarlet並應用xpath過濾器。

cat file.xml | XML SEL -t -m 'xpathExpression' -v「elemName '文字' -v 'elname' -n -m表達 -v值 '' 包括文字 -n換行符

因此,對於你的XPath的xpath表達式將是// myel/@名稱 它將提供兩個屬性值。

非常方便的工具。

HTH

+0

XMLStarlet最近似乎沒有更新太多 – Vihung 2012-10-02 14:21:16

0

您的測試文件在test.xml中。

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

它有它的缺陷,例如,如果它不嚴格只要每個MYEL是在一行上你要「正常化」的XML文件中的第一(所以每個MYEL是一個獨立的行)

1

回答原來的問題,假設XML文件 「的test.xml」 包含:

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

cat text.xml | tr -s "\"" " " | awk '{printf "%s,\n", $3}'