Domanda

I am working on parsing an XML to a CSV. Ran into an article @ Convert an XML file to CSV file using java and was able to verify the solution using the data.xml and style.xsl

Building on the xml data.xml, was wondering what changes would be needed on the style.xsl if mutiple values were present for some of the elements.

For example, if multiple OSs were present sometimes in the data.xml

<?xml version="1.0"?>
<Sites>
<Site id="101" name="NY-01" location="New York">
<Hosts>
   <Host id="1001">
   <Host_Name>srv001001</Host_Name>
   <IP_address>10.1.2.3</IP_address>
   <OS>Windows</OS>
   <Load_avg_1min>1.3</Load_avg_1min>
   <Load_avg_5min>2.5</Load_avg_5min>
   <Load_avg_15min>1.2</Load_avg_15min>
</Host>
<Host id="1002">
   <Host_Name>srv001002</Host_Name>
   <IP_address>10.1.2.4</IP_address>
   <OS>Linux, Windows</OS>
   <Load_avg_1min>1.4</Load_avg_1min>
   <Load_avg_5min>2.5</Load_avg_5min>
   <Load_avg_15min>1.2</Load_avg_15min>
</Host>
<Host id="1003">
   <Host_Name>srv001003</Host_Name>
   <IP_address>10.1.2.5</IP_address>
   <OS>Linux</OS>
   <Load_avg_1min>3.3</Load_avg_1min>
   <Load_avg_5min>1.6</Load_avg_5min>
   <Load_avg_15min>1.8</Load_avg_15min>
</Host>
<Host id="1004">
   <Host_Name>srv001004</Host_Name>
   <IP_address>10.1.2.6</IP_address>
   <OS>Linux, NetBSD</OS>
   <Load_avg_1min>2.3</Load_avg_1min>
   <Load_avg_5min>4.5</Load_avg_5min>
   <Load_avg_15min>4.2</Load_avg_15min>
</Host>     

È stato utile?

Soluzione

Try it this way?

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

<xsl:template match="/">
    <xsl:text>Host_Name,IP_address,OS,Load_avg_1min,Load_avg_5min,Load_avg_15min&#10;</xsl:text>
    <xsl:for-each select="Sites/Site/Hosts/Host">
        <xsl:value-of select="concat(Host_Name,',',IP_address,',&quot;',OS,'&quot;,',Load_avg_1min,',',Load_avg_5min,',',Load_avg_15min,'&#10;')"/>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Or, if you prefer:

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

<xsl:template match="/">
    <xsl:text>Host_Name,IP_address,OS,Load_avg_1min,Load_avg_5min,Load_avg_15min&#10;</xsl:text>
    <xsl:for-each select="Sites/Site/Hosts/Host">
        <xsl:for-each select="*">
            <xsl:text>"</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>"</xsl:text>
            <xsl:if test="position()!=last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:if test="position()!=last()">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Note that both assume none of your "fields" contains a " quotation mark.

Altri suggerimenti

If you have comma-separated values in an element, you can replace it when transforming using translate(node, character-to-be-replaced, replacement-character):

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

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

    <xsl:template match="Host">
        <xsl:value-of select="ancestor::Site/@id"/><xsl:text>, </xsl:text>
        ...

        <xsl:value-of select="@id"/><xsl:text>, </xsl:text>
        <xsl:value-of select="Host_Name"/><xsl:text>, </xsl:text>
        <xsl:value-of select="IP_address"/><xsl:text>, </xsl:text>
        <xsl:value-of select="translate(OS, ',', ';')"/><xsl:text>, </xsl:text>
        ...
    </xsl:template>

</xsl:stylesheet>

You can use it for all elements that might have commas, since if the comma is not found, the text will be copied without any changes.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top