Разбор XML с использованием терминала Unix - PullRequest
11 голосов
/ 27 августа 2008

Иногда мне нужно быстро извлечь некоторые произвольные данные из файлов XML, чтобы поместить их в формат CSV. Каковы ваши лучшие практики для этого в терминале Unix? Мне бы хотелось несколько примеров кода, например, как я могу решить следующую проблему?

Пример ввода XML:

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

Мой желаемый выход CSV:

Foo,
Bar,

Ответы [ 7 ]

11 голосов
/ 27 августа 2008

Ответ Питера правильный, но выводит перевод строки в конце.

<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 в стандартный вывод.

9 голосов
/ 27 августа 2008

Используйте процессор командной строки XSLT, такой как xsltproc , саксон или 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>&#10;</xsl:text>
    </xsl:template> 
</xsl:stylesheet>
6 голосов
/ 12 сентября 2008

XMLStarlet - это набор инструментов командной строки для запроса / редактирования / проверки / преобразования XML-документы (дополнительную информацию см. http://xmlstar.sourceforge.net/)

Нет файлов для записи, просто передайте файл в xmlstarlet и примените фильтр xpath.

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

-м выражение -v значение '' включены буквально -n новая строка

Так что для вашего xpath выражение xpath будет // myel / @ name который предоставил бы два значения атрибута.

Очень удобный инструмент.

5 голосов
/ 27 августа 2008

Если вам просто нужны атрибуты имени любого элемента, вот быстрое, но неполное решение.

(Ваш пример текста находится в файле пример )

grep "name" пример | cut -d "\" "-f2,2 | xargs -I {} echo "{},"

2 голосов
/ 21 января 2014

Отвечая на исходный вопрос, предполагая, что xml-файл - это «test.xml», содержащий:

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

cat text.xml | tr -s "\"" " " | awk '{printf "%s,\n", $3}'
2 голосов
/ 27 августа 2008

Вот небольшой скрипт ruby, который делает точно , что задает ваш вопрос (вытяните атрибут с именем 'name' из элементов с именем 'myel'). Должно быть легко обобщить

#!/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'] }
1 голос
/ 18 сентября 2008

ваш тестовый файл находится в test.xml.

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

У него есть свои подводные камни, например, если строго не указано, что каждый myel находится в одной строке, вы должны сначала "нормализовать" файл XML (поэтому каждый myel на отдельной строке)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...