Domanda

Devo trasporre un file XML come questo:

<?xml version="1.0" encoding="UTF-8"?>
<products>
    <product id="10" name="Widget 1" price="15.99" category_code="T" category="Toys" manufacturer_code="SC1" manufacturer="Some Company 1" />
    <product id="10" name="Widget 1" price="15.99" category_code="E" category="Electronics" manufacturer_code="SC1" manufacturer="Some Company 1" />
    <product id="10" name="Widget 1" price="15.99" category_code="T" category="Toys" manufacturer_code="SC2" manufacturer="Some Company 2" />
    <product id="10" name="Widget 1" price="15.99" category_code="E" category="Electronics" manufacturer_code="SC2" manufacturer="Some Company 2" />
    <product id="10" name="Widget 1" price="15.99" category_code="T" category="Toys" manufacturer_code="SC3" manufacturer="Some Company 3" />
    <product id="10" name="Widget 1" price="15.99" category_code="E" category="Electronics" manufacturer_code="SC3" manufacturer="Some Company 3" />
    <product id="11" name="Widget 2" price="21.99" category_code="V" category="Video Games" manufacturer_code="SC4" manufacturer="Some Company 4" />
    <product id="12" name="Widget 3" price="10.99" category_code="T" category="Toys" manufacturer_code="SC1" manufacturer="Some Company 2" />
</products>

a un file di testo delimitato da virgola o una tabella HTML correttamente formata che include solo una riga per ogni prodotto, qualcosa del genere:

id,name,price,category_code_1,category_1,category_code_2,category_2,manufacturer_code_1,manufacturer_1,manufacturer_code_2,manufacturer_2,manufacturer_code_3,manufacturer_3
    10, Widget 1, 15.99, T, Toys, E, Electronics, SC1, Some Company 1, SC2, Some Company 2, SC3, Some Company 3 
    11, Widget 2, 21.99, V, Video Games,,, SC4, Some Company 4,,,,
    12, Widget 3, 10.99, T, Toys,,, SC1, Some Company 2,,,,

Come noteresti, i dati XML possono essere considerati come il risultato di tre tabelle unite: Product, Product_Category e Product_Manufacter. Ogni prodotto può appartenere a più categorie e avere più produttori. Naturalmente i dati reali con cui ho a che fare sono più complessi e in un dominio totalmente diverso, ma questo campione descrive correttamente il problema.

Ho una conoscenza molto limitata di XSLT e, con l'aiuto di SO e altre risorse sull'attenzione, ho messo insieme un foglio di stile che in parte mi fornisce ciò di cui ho bisogno:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:key name="key_product_group" match="product" use="@id"/>
    <xsl:key name="key_category_group" match="product" use="concat(
             @id,
             @category_code,
             @category)"/>
    <xsl:key name="key_manufacturer_group" match="product" use="concat(
             @id,
             @manufacturer_code,
             @manufacturer)"/>
    <xsl:variable name="var_max_category_group"  >
        <xsl:for-each select="//product[generate-id(.) = generate-id(key('key_product_group',@id) )]">
            <xsl:sort select="count(key('key_product_group',@id )[generate-id() = generate-id(key('key_category_group',
                                   concat(@id,
                                  @category_code,
                                  @category)))])" order="descending"/>
            <xsl:if test="position() = 1">
                <xsl:value-of select="count(key('key_product_group',@id )[generate-id() = generate-id(key('key_category_group',
                                   concat(@id,
                                  @category_code,
                                  @category)))])"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="var_max_manufacturer_group">
        <xsl:for-each select="//product[generate-id(.) = generate-id(key('key_product_group',@id) )]">
            <xsl:sort select="count(key('key_product_group',@id )[generate-id() = generate-id(key('key_manufacturer_group',
                                   concat(@id,
                                  @category_code,
                                  @category)))])" order="descending"/>
            <xsl:if test="position() = 1">
                <xsl:value-of   select="count(key('key_product_group',@id )[generate-id() = generate-id(key('key_manufacturer_group',
                                   concat(@id,
                                  @manufacturer_code,
                                  @manufacturer)))])"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:template match="/">
        <xsl:text>id,</xsl:text>
        <xsl:text>name,</xsl:text>
        <xsl:text>price,</xsl:text>
        <xsl:call-template name="loop_pcat">
            <xsl:with-param name="count" select="$var_max_category_group"/>
        </xsl:call-template>
        <xsl:call-template name="loop_pmf">
            <xsl:with-param name="count" select="$var_max_manufacturer_group"/>
        </xsl:call-template>
        <br></br>
        <xsl:variable name="var_group"
                          select="//product[generate-id(.) = generate-id(key('key_product_group',@id)[1])]"/>
        <xsl:for-each select="$var_group">
            <xsl:sort order="ascending" select="@id"/>
            <xsl:value-of select="@id"/>,
            <xsl:value-of select="@name"/>,
            <xsl:value-of select="@price"/>,
            <xsl:for-each select="key('key_product_group',@id )[generate-id() = generate-id(key('key_category_group',
                                   concat(@id,
                                  @category_code,
                                  @category)))]">
                <xsl:value-of select="@category_code"/>,
                <xsl:value-of select="@category"/>,
            </xsl:for-each>
            <xsl:for-each select="key('key_product_group',@id )[generate-id() = generate-id(key('key_manufacturer_group',
                                   concat(@id,
                                  @manufacturer_code,
                                  @manufacturer)))]">
                <xsl:value-of select="@manufacturer_code"/>,
                <xsl:value-of select="@manufacturer"/>,
            </xsl:for-each>
            <br></br>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="loop_pcat">
        <xsl:param name="count" select="1"/>
        <xsl:param name="limit" select="$count+1"/>
        <xsl:if test="$count > 0">
            <xsl:value-of select="concat('category_code_',$limit - $count)"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="concat('category_',$limit - $count)"/>
            <xsl:text>,</xsl:text>
            <xsl:call-template name="loop_pcat">
                <xsl:with-param name="count" select="$count - 1"/>
                <xsl:with-param name="limit" select="$limit"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    <xsl:template name="loop_pmf">
        <xsl:param name="count" select="1"/>
        <xsl:param name="limit" select="$count+1"/>
        <xsl:if test="$count > 0">
            <xsl:value-of select="concat('manufacturer_code_',$limit - $count)"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="concat('manufacturer_',$limit - $count)"/>
            <xsl:text>,</xsl:text>
            <xsl:call-template name="loop_pmf">
                <xsl:with-param name="count" select="$count - 1"/>
                <xsl:with-param name="limit" select="$limit"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Il foglio di stile di cui sopra produce i seguenti risultati:

id,name,price,category_code_1,category_1,category_code_2,category_2,manufacturer_code_1,manufacturer_1,manufacturer_code_2,manufacturer_2,manufacturer_code_3,manufacturer_3,
10, Widget 1, 15.99, T, Toys, E, Electronics, SC1, Some Company 1, SC2, Some Company 2, SC3, Some Company 3, 
11, Widget 2, 21.99, V, Video Games, SC4, Some Company 4, 
12, Widget 3, 10.99, T, Toys, SC1, Some Company 2, 

L'output ha almeno un problema grave: tutte le colonne non esistono in ciascuna riga, ad esempio la riga 2 e 3 mancano Category_Code_2 e Category_2 e Manufature_Code e produttore 2 e 3. Sono sicuro che ci sono altri problemi con il foglio di stile Styles Inoltre, e non ho idea di come si esibirà su un file XML relativamente grande, ma per ora apprezzerei molto il tuo aiuto nel far produrre il foglio di stile il formato di output desiderato.

Grazie

MRSA

Nessuna soluzione corretta

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