Steven Cook
Steven Cook

Reputation: 11

create multiple xmls from xsl transformation and place data into those xml's based on the tag attributes of source xml

I'm trying to create different xml files based on language name using xsl 2.0. In my input xml, here there are only 2 languages, "en" and "es".

  1. All the "en" based persons will go to en.xml and
  2. All the "es" based persons will go to es.xml and
  3. All the person who have both "en" and "es" will have to go to both en.xml and es.xml.

My Input XML: source xml is about the list of persons, their addresses and languages

<persons>
    <person name="Alice">
        <Addresses>
            <Address type ="personal">
                <language name = "en">
                </language>
            </Address>
            <Address type ="business">
                <language name = "en">
                </language>
            </Address>
        </Addresses>
    </person>
    <person name="Bob">
        <Addresses>
            <Address type ="personal">
                <language name = "es">
                </language>
            </Address>
            <Address type ="business">
                <language name = "es">
                </language>
            </Address>
        </Addresses>
    </person>
    <person name="Stacy">
        <Addresses>
            <Address type ="personal">
                <language name = "en">
                </language>
            </Address>
            <Address type ="business">
                <language name = "es">
                </language>
            </Address>
        </Addresses>
    </person>
</persons>

output file en.xml will have:

all the persons containing language attribute value = "en" should go to the en.xml file. In this case, both Alice and Stacy will need to go to en.xml

    <person name="Alice">
        <Addresses>
            <Address type ="personal">
                <language name = "en">
                </language>
            </Address>
            <Address type ="business">
                <language name = "en">
                </language>
            </Address>
        </Addresses>
    </person>
        <person name="Stacy">
        <Addresses>
            <Address type ="personal">
                <language name = "en">
                </language>
            </Address>
            <Address type ="business">
                <language name = "es">
                </language>
            </Address>
        </Addresses>
    </person>

output file es.xml will have:

all the persons containing language attribute value = "es" should go to the en.xml file. In this case, both Bob and Stacy will need to go to es.xml

    <person name="Bob">
        <Addresses>
            <Address type ="personal">
                <language name = "es">
                </language>
            </Address>
            <Address type ="business">
                <language name = "es">
                </language>
            </Address>
        </Addresses>
    </person>
    <person name="Stacy">
        <Addresses>
            <Address type ="personal">
                <language name = "en">
                </language>
            </Address>
            <Address type ="business">
                <language name = "es">
                </language>
            </Address>
        </Addresses>
    </person>

My XSL so far:

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

<xsl:output method="xml" indent="yes" name="xml"/>

<xsl:template match="/">
    <xsl:for-each select="//persons">
       <xsl:variable name="filename"
             select="concat('allpersons/',//persons/person/Addresses/Address/language/@name,'.xml')" />
       <xsl:value-of select="$filename" />  <!-- Creating  -->
       <xsl:result-document href="{$filename}" format="xml">
             <xsl:value-of select="."/>
       </xsl:result-document>
     </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Solution should not contain static matching of attributes like "en", "es".. beacause there are lot of languages. Any Help is well appreciated?

References: http://www.ibm.com/developerworks/xml/library/x-tipmultxsl/index.html

Upvotes: 1

Views: 387

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167571

Here is an XSLT 2.0 sample:

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

<xsl:output indent="yes"/>

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* , node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="persons">
  <xsl:for-each-group select="person" group-by="Addresses/Address/language/@name">
    <xsl:result-document href="{current-grouping-key()}.xml">
      <xsl:apply-templates select="current-group()"/>
    </xsl:result-document>
  </xsl:for-each-group>
</xsl:template>

<xsl:template match="person/Addresses">
  <xsl:if test="Address/language/@name = current-grouping-key()">
    <xsl:next-match/>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

I am not sure you really want to create those result files without a root but if you want a root change the persons template to

<xsl:template match="persons">
  <xsl:for-each-group select="person" group-by="Addresses/Address/language/@name">
    <xsl:result-document href="{current-grouping-key()}.xml">
      <persons>
        <xsl:apply-templates select="current-group()"/>
      </persons>
    </xsl:result-document>
  </xsl:for-each-group>
</xsl:template>

Upvotes: 1

Related Questions