Преобразование XML в CSV с использованием XSLT

Я пытаюсь преобразовать свой ввод xml в вывод csv, как показано ниже.

INPUT файл:

      <Customer>
   <item>
      <CustomerID>100000069</CustomerID>
      <CustomerGroup>EX</CustomerGroup>
      <CustomerName>Test Mehmet</CustomerName>
      <CustomerStreet>Street</CustomerStreet>
      <HouseNumber>123</HouseNumber>
      <CustomerCity>Ismaning</CustomerCity>
      <CustomerZip>85737</CustomerZip>
      <CustomerCountry>DE</CustomerCountry>
   </item>
</Customer>

XSL:

      <?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name='newline'>
<xsl:text>
</xsl:text>
</xsl:variable>
<xsl:template match="/Customer">
<xsl:value-of select="concat('&quot;CustomerID&quot;;&quot;CustomerGroup&quot;;&quot;CustomerName&quot;;&quot;CustomerStreet&quot;;&quot;HouseNumber&quot;;&quot;CustomerCity&quot;;&quot;CustomerZIP&quot;;&quot;CustomerCountry&quot;',$newline)"/>
<xsl:for-each select="./item">
<xsl:value-of select="concat('&quot;',./CustomerID,'&quot;;&quot;',./CustomerGroup,'&quot;;&quot;',./CustomerName,'&quot;;&quot;',./CustomerStreet,'&quot;;&quot;',./HouseNumber,'&quot;;&quot;',./CustomerCity,'&quot;;&quot;',./CustomerZIP,'&quot;;&quot;',./CustomerCountry,'&quot;',$newline)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Мой исходный вывод:

«CustomerID»; «CustomerGroup»; «CustomerName»; «CustomerStreet»; «HouseNumber»; «CustomerCity»; «CustomerZIP»; «CustomerCountry» «100000069»; «EX»; «Test Mehmet»; «Street»; «123 ";" Исманинг ";" ";" DE "

Ожидаемый результат:

Мне нужно изменить все пустые значения на «null». ниже мой ожидаемый результат.

«CustomerID»; «CustomerGroup»; «CustomerName»; «CustomerStreet»; «HouseNumber»; «CustomerCity»; «CustomerZIP»; «CustomerCountry» «100000069»; «EX»; «Test Mehmet»; «Street»; «123 ";" Исманинг "; null;" DE "

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

1 ответ

Предполагая, что вы ограничены XSLT 1.0, я бы посоветовал вам сделать это следующим образом:

XSLT 1.0

      <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="/Customer">
    <!-- header row -->
    <xsl:text>"CustomerID";"CustomerGroup";"CustomerName";"CustomerStreet";"HouseNumber";"CustomerCity";"CustomerZIP";"CustomerCountry"&#10;</xsl:text>
    <!-- data rows -->
    <xsl:for-each select="item">
        <xsl:call-template name="cell">
            <xsl:with-param name="data" select="CustomerID"/>
        </xsl:call-template>
        <xsl:text>;</xsl:text>
        <xsl:call-template name="cell">
            <xsl:with-param name="data" select="CustomerGroup"/>
        </xsl:call-template>
        <xsl:text>;</xsl:text>
        <xsl:call-template name="cell">
            <xsl:with-param name="data" select="CustomerName"/>
        </xsl:call-template>
        <xsl:text>;</xsl:text>
        <xsl:call-template name="cell">
            <xsl:with-param name="data" select="CustomerStreet"/>
        </xsl:call-template>
        <xsl:text>;</xsl:text>
        <xsl:call-template name="cell">
            <xsl:with-param name="data" select="HouseNumber"/>
        </xsl:call-template>
        <xsl:text>;</xsl:text>
        <xsl:call-template name="cell">
            <xsl:with-param name="data" select="CustomerCity"/>
        </xsl:call-template>
        <xsl:text>;</xsl:text>
        <xsl:call-template name="cell">
            <xsl:with-param name="data" select="CustomerZip"/>
        </xsl:call-template>
        <xsl:text>;</xsl:text>
        <xsl:call-template name="cell">
            <xsl:with-param name="data" select="CustomerCountry"/>
        </xsl:call-template>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

<xsl:template name="cell">
    <xsl:param name="data"/>
    <xsl:choose>
        <xsl:when test="string($data)">
            <xsl:text>"</xsl:text>
            <xsl:value-of select="$data"/>
            <xsl:text>"</xsl:text>
        </xsl:when>
        <xsl:otherwise>null</xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

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

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

      <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="/Customer">
    <!-- header row -->
    <xsl:text>"CustomerID";"CustomerGroup";"CustomerName";"CustomerStreet";"HouseNumber";"CustomerCity";"CustomerZIP";"CustomerCountry"&#10;</xsl:text>
    <!-- data rows -->
    <xsl:for-each select="item">
        <xsl:for-each select="*">
            <xsl:choose>
                <xsl:when test="string(.)">
                    <xsl:text>"</xsl:text>
                    <xsl:value-of select="."/>
                    <xsl:text>"</xsl:text>
                </xsl:when>
                <xsl:otherwise>null</xsl:otherwise>
            </xsl:choose>
            <xsl:if test="position()!=last()">;</xsl:if>
        </xsl:for-each>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
Другие вопросы по тегам