xsl: for-each не возвращает никаких значений - PullRequest
0 голосов
/ 02 июня 2019

Я пытаюсь преобразовать XML-файл, содержащий несколько узлов (node6 / total), в выходной файл CSV, но for-each в XSL не возвращает ничего на выходе.

Код XML:

<?xml version='1.0' encoding='utf-8'?>
<File xmlns='urn:uk.co.visitors.v1'>
<Reference>175008-00123</Reference>
<Description>XTR22_2019-01-21</Description>
<Created>2019-01-21T13:45:46</Created>
<node1>
    <node2>
        <ref>REFERENCE</ref>
        <num>12345</num>
        <node3>
            <node4>
                <ref1>012345</ref1>
                <name>scarface</name>
                <location>1876 main street</location>
                <date>2019-01-21</date>
                <ref2>012345</ref2>
                <cost>0.00</cost>
                <paid>9.99</paid>
                <node5>
                    <node6>
                        <detail>check-in</detail>
                        <ondate>2019-01-21</ondate>
                        <time>08:00:00</time>
                        <total>40</total>
                        <update>FALSE</update>
                    </node6>
                    <node6>
                        <detail>check-in</detail>
                        <ondate>2019-01-22</ondate>
                        <time>23:00:00</time>
                        <total>10</total>
                        <update>TRUE</update>
                    </node6>
                    <node6>
                        <detail>check-out</detail>
                        <ondate>2019-01-25</ondate>
                        <time>11:00:00</time>
                        <total>5</total>
                        <update>TRUE</update>
                    </node6>
                </node5>
            </node4>
        </node3>
    </node2>
</node1>
</File>

XSL-код:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output method="text" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="no" />

    <xsl:variable name="delimiter" select="'&#59;'" />
    <xsl:variable name="newline" select="'&#10;'" />

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

    <xsl:template match="/">
        <xsl:text>column1;column2;total</xsl:text>
        <xsl:value-of select="$newline" />
        <xsl:text>X45</xsl:text>
        <xsl:value-of select="$delimiter" />
        <xsl:text>NONE</xsl:text>
        <xsl:value-of select="$delimiter" />

        <xsl:for-each select="/File/node1/node2/node3/node4/node5/node6/total">
            <xsl:value-of select="total" />
            <xsl:value-of select="$delimiter" />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

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

Ожидаемый результат - файл CSV, содержащий 3 заголовка и 3 строки данных:

column1;column2;total;
X45;NONE;40;
X45;NONE;10;
X45;NONE;5;

Текущий вывод выглядит следующим образом:

column1;column2;total;
X45;NONE;

Файл, с которым я работаю:значительно больше, но это пример, основанный на приведенном выше коде.

Буду признателен за любую помощь или совет, как этого добиться.

1 Ответ

0 голосов
/ 02 июня 2019

Как уже упоминалось, элементы находятся в пространстве имен.Один из подходов заключается в использовании префикса пространства имен ns1 во всех выражениях XPath.Тогда ваш for-each XPath будет выглядеть так:

/ns1:File/ns1:node1/ns1:node2/ns1:node3/ns1:node4/ns1:node5/ns1:node6

И вы также должны использовать его на ns1:total.

Другой способ - установить атрибут xpath-default-namespace="urn:uk.co.visitors.v1"элемента xsl:stylesheet.Затем вы можете оставить свой код как есть (как в коде ниже).

Две другие вещи: кроме удаления total из выражения for-each, вы должны переместить X45 и NONE текстов в цикл for-each.

Объединив все это, ваш шаблон можно упростить до следующего:

<xsl:template match="/">
    <xsl:text>column1;column2;total</xsl:text>
    <xsl:value-of select="$newline" />
    <xsl:for-each select="/File/node1/node2/node3/node4/node5/node6">
        <xsl:text>X45</xsl:text>
        <xsl:value-of select="$delimiter" />
        <xsl:text>NONE</xsl:text>
        <xsl:value-of select="$delimiter" />
        <xsl:value-of select="total" />
        <xsl:value-of select="concat($delimiter,$newline)" />
    </xsl:for-each>
</xsl:template>

Это даст вам желаемый результат.Это может быть дополнительно упрощено до

<xsl:template match="/">
    <xsl:text>column1;column2;total</xsl:text>
    <xsl:value-of select="$newline" />
    <xsl:for-each select="/File/node1/node2/node3/node4/node5/node6">
        <xsl:value-of select="concat('X45',$delimiter,'NONE',$delimiter,total,$delimiter,$newline)" />
    </xsl:for-each>
</xsl:template>

, что дает тот же результат.

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