Двухфазное преобразование с использованием XSLT 2.0

Я пытаюсь взять файл CSV в качестве входных данных и преобразовать его в XML. Я новичок в XSLT и нашел способ преобразовать CSV в XML (используя пример из Эндрю Велч) вот так:

Входной файл CSV:

car manufacturer,model,color,price,inventory
subaru,outback,blue,23195,54
subaru,forester,silver,20495,23

И мой выходной XML будет:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
   <row>
      <column name="car manufacturer">subaru</column>
      <column name="model">outback</column>
      <column name="color">blue</column>
      <column name="price">23195</column>
      <column name="inventory">54</column>
   </row>
   <row>
      <column name="car manufacturer">subaru</column>
      <column name="model">forester</column>
      <column name="color">silver</column>
      <column name="price">20495</column>
      <column name="inventory">23</column>
   </row>
</rows>

Мой желаемый результат на самом деле похож на:

<stock>
   <model>
      <car>subaru outback</car>
      <color>blue</color>
      <price>23195</price>
      <inventory>54</inventory>
   </model>
   <model>
      <car>subaru forester</car>
      <color>silver</color>
      <price>20495</price>
      <inventory>23</inventory>
   </model>
</stock>

Я прочитал, что лучше всего было бы использовать двухфазное преобразование. Преобразование CSV в XML выполняется с использованием XSLT 2.0, поэтому я подумал, что двухфазное преобразование будет выполняться с его использованием и без использования функции набора узлов.

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

Кто-нибудь может помочь в том, как можно сделать двухфазное преобразование? У меня возникли проблемы с передачей выхода фазы 1 как входа фазы 2?

У меня пока что-то вроде этого:

<xsl:import href="csv2xml.xsl"/>
<xsl:output method="xml" indent="yes" />

<xsl:variable name="intermediate">
    <xsl:apply-templates select="/" mode="csv2xml"/>
</xsl:variable>

<xsl:template match="rows" name="main">

 **[This is what I'm having trouble with]**

</xsl:template>

person eyedrop    schedule 24.04.2011    source источник
comment
Это кажется неэффективным использованием XSLT. Вы можете напрямую проанализировать CSV и сгенерировать XML непосредственно на обычном процедурном языке (например, Perl, Python и т. Д.). XSLT - не лучший инструмент для анализа данных, отличных от XML.   -  person ewh    schedule 25.04.2011


Ответы (3)


Эта таблица стилей XSLT 2.0:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="vLines"
         select="tokenize(unparsed-text('test.txt'),'(&#xD;)?&#xA;')"/>
        <xsl:variable name="vHeaders"
         select="tokenize($vLines[1],',')"/>
        <stock>
            <xsl:for-each select="$vLines[position()!=1]">
                <model>
                    <xsl:variable name="vColumns" select="tokenize(.,',')"/>
                    <xsl:for-each select="$vColumns">
                        <xsl:variable name="vPosition" select="position()"/>
                        <xsl:variable name="vHeader"
                         select="$vHeaders[$vPosition]"/>
                        <xsl:choose>
                            <xsl:when test="$vHeader = 'car manufacturer'">
                                <column name="car">
                                    <xsl:value-of
                                     select="(.,$vColumns[
                                                   index-of($vHeaders,'model')
                                                ])"/>
                                </column>
                            </xsl:when>
                            <xsl:when test="$vHeader = 'model'"/>
                            <xsl:otherwise>
                                <column name="{$vHeader}">
                                    <xsl:value-of select="."/>
                                </column>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each>
                </model>
            </xsl:for-each>
        </stock>
    </xsl:template>
</xsl:stylesheet>

Выход:

<stock>
    <model>
        <column name="car">subaru outback</column>
        <column name="color">blue</column>
        <column name="price">23195</column>
        <column name="inventory">54</column>
    </model>
    <model>
        <column name="car">subaru forester</column>
        <column name="color">silver</column>
        <column name="price">20495</column>
        <column name="inventory">23</column>
    </model>
</stock>

Примечание. В XSLT 3.0 вы сможете применять шаблоны к элементам в целом.

ИЗМЕНИТЬ: правильные имена.

person Community    schedule 24.04.2011
comment
Спасибо, @Alejandro. Я смог извлечь уроки из вашего ответа, чтобы получить тот же результат, что и я. - person eyedrop; 25.04.2011
comment
@eyedrop: Ваш актуальный вопрос: кто-нибудь может помочь в том, как можно сделать двухфазное преобразование? У меня проблемы с передачей выхода фазы 1 как входа фазы 2? Ответ @ Alejandro не отвечает на фактический вопрос - он предоставляет решение для фазы 1. Ответ, который точно отвечает на ваш вопрос, - это ответ @ Michael-Kay. Пожалуйста, примите его ответ! - person Dimitre Novatchev; 25.04.2011

Я не вижу причин, по которым это преобразование требует двух этапов - за исключением, возможно, возможности повторно использовать существующий код для одного из этапов.

Однако, когда вам действительно нужны две фазы, общая модель такова:

<xsl:template match="/">
  <xsl:variable name="phase-1-result">
    <xsl:apply-templates select="/" mode="phase-1"/>
  </xsl:variable>
  <xsl:apply-templates select="$phase-1-result" mode="phase-2"/>
</xsl:template>

с шаблонными правилами для фазы 1 и фазы 2 (и их вызовов apply-templates) все находятся в режиме фаза-1 или фаза-2 соответственно.

person Michael Kay    schedule 24.04.2011

Вы можете найти здесь пример того, как это сделать с XSLT 3.0:

http://www.stylusstudio.com/tutorials/intro-xslt-3.html

См. Раздел «Манипуляции с текстом».

person Pascal Sartoretti    schedule 12.03.2012