2008-08-26 13 views
11

Parfois, j'ai besoin d'extraire rapidement des données arbitraires à partir de fichiers XML pour les mettre dans un format CSV. Quelles sont vos meilleures pratiques pour ce faire dans le terminal Unix? J'aimerais des exemples de code, par exemple comment puis-je résoudre le problème suivant?Analyse XML à l'aide du terminal unix

Exemple entrée XML:

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

Ma souhaitée sortie CSV:

Foo, 
Bar, 

Répondre

5

Si vous voulez juste les attributs de nom d'un élément, voici une solution rapide, mais incomplète.

(Votre texte exemple dans le fichier exemple)

grep "nom" exemple | cut -d "\" » -f2,2 | xargs -I {} echo "{}",

9

Utilisez un processeur XSLT de ligne de commande tel que xsltproc, saxon ou xalan pour analyser le XML et générer CSV. Voici an example, qui pour votre cas est la feuille de style:

<?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 est correct, mais il produit un saut de ligne de fuite

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

Just. exécuter par exemple

xsltproc stylesheet.xsl source.xml 

pour générer les résultats CSV dans la sortie standard.

1

Voici un petit script Ruby qui ne exactement ce que votre question demande (tirer un attribut appelé «nom» sur des éléments appelés «myel»). Devrait être facile de généraliser

#!/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 est une boîte à outils de ligne de commande pour interroger/modifier/vérifier/transformer documents XML (pour plus d'informations, voir http://xmlstar.sourceforge.net/)

Aucun fichier à écrire, juste tuyau de votre fichier xmlstarlet et appliquer un filtre xpath.

cat fichier.xml | xml sel -t -m 'XPathExpression' -v 'littérale' -v 'elname 'elemName'' -n -m expression valeur -v '' inclus littérale -n nouvelle ligne

Donc, pour votre XPath la L'expression xpath serait // myel/@ name qui fournirait les deux valeurs d'attribut.

Outil très pratique.

HTH

+0

XMLStarlet ne semble pas avoir été mis à jour beaucoup récemment – Vihung

0

votre fichier de test est en test.xml.

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

Il a ses pièges, par exemple si elle est pas strictement donné que chaque MYEL est sur une ligne que vous avez à « normaliser » le fichier xml premier (pour chaque MYEL est sur une ligne séparée)

1

Répondant à la question initiale, en supposant un fichier xml est "test.xml" qui contient:

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

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