XML в CSV с вложенными элементами (xsltproc)

Я пытаюсь преобразовать XML в CSV с помощью xsltproc.

в настоящее время у меня есть

--XSL template
<xsl:strip-space elements="*" />

<xsl:template match="/*/child::*">
<xsl:for-each select="child::*">
<xsl:if test="position() != last()">"<xsl:value-of select="normalize-space(.)"/>",            </xsl:if>
<xsl:if test="position()  = last()">"<xsl:value-of select="normalize-space(.)"/>"  <xsl:text>&#xD;</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>

--XML (they are two separate files 
    <root>
<summary>
    <field1>a</field1>
    <field2>b</field2>
    <field3>c</field3>
    <field4>d</field4>
        <data>
            <field5>e</field5>
            <field6>f</field6>
        </data>
        <user_info>
            <field7>g</field7>
            <field8>h</field8>
        </user_info>
   </summary>
 </root>

Но как включить вложенные элементы из XML? У меня есть 3 вложенных элемента.

В настоящее время я получаю «поле один», «поле два», «поле три», «поле четыре», «поле 5,6,7,8,9,10»

Я хотел бы увидеть

field1, field 2, field 3, field 4, field 5, field 6, field 7, field 8
"a", "b", "c", "d", "e", "f", "g", "h"

person user112570    schedule 03.01.2014    source источник
comment
Пожалуйста, опубликуйте пример исходного XML и ожидаемого результата.   -  person michael.hor257k    schedule 03.01.2014
comment
Боюсь, это не очень хороший пример: имена элементов недействительны (содержат пробелы). Также неясно, какие элементы должны быть включены в результат. В идеале вы должны заранее знать структуру XML, чтобы иметь возможность присваивать им имена явно по имени и по пути. В противном случае вам понадобятся некоторые критерии выбора, например: имя элемента начинается с поля.   -  person michael.hor257k    schedule 03.01.2014


Ответы (1)


Сохраните все элементы, имя которых начинается с «поля», в переменной. Затем дважды повторите содержимое $fields. В первый раз выведите все имена элементов, во второй раз содержимое каждого элемента.

Таким образом, вам не придется вмешиваться во вложенную структуру. Эта строка:

<xsl:if test="position() != last()">

гарантирует, что запятая не будет вставлена, если обрабатывается последний элемент.

Предполагая правильный ввод (без пробелов в именах элементов), это возможное решение:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="fields" select="//*[starts-with(name(),'field')]"/>

<xsl:template match="/root">
  <xsl:for-each select="$fields">
     <xsl:value-of select="name()"/>
     <xsl:if test="position() != last()">
        <xsl:text>,&#32;</xsl:text>
     </xsl:if>
  </xsl:for-each>

  <xsl:text>&#10;</xsl:text>

  <xsl:for-each select="$fields">
     <xsl:text>"</xsl:text>
     <xsl:value-of select="."/>
     <xsl:text>"</xsl:text>
     <xsl:if test="position() != last()">
        <xsl:text>,&#32;</xsl:text>
     </xsl:if>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Дает вам следующий вывод:

field1, field2, field3, field4, field5, field6, field7, field8
"a", "b", "c", "d", "e", "f", "g", "h"
person Mathias Müller    schedule 03.01.2014