xsltxslt-1.0

How to create a URL query string from a dynamic complex XML structure using XSLT 1.0


I need to be able to transform various XML structures into URL query strings. The tricky part is, that there are multiple XML structures, so the transformation would have to be dynamic/generic.

Here are two example XMLs.

Example 1:

<?xml version="1.0" encoding="UTF-8"?>
<query1>
    <first_name>foo</first_name>
    <last_name>bar</last_name>
    <age/>
</query1>

Example 2:

<?xml version="1.0" encoding="UTF-8"?>
<query2>
    <occupation>developer</occupation>
    <org_structure/>
    <team>TECH</team>
</query2>

This should be the result when transforming the first example:

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <query>?first_name=foo&amp;last_name=bar</query>
</result>

This should be the result when transforming the second example:

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <query>?occupation=developer&amp;team=TECH</query>
</result>

Note that any of the XML elements may be empty, in which case no query parameter should be created.

Is there a way to do this with one XSLT 1.0 transformation?

Thank you!


Solution

  • I think this will work for both your examples:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/*">
        <result>
            <query>
                <xsl:text>?</xsl:text>
                <xsl:for-each select="*[text()]">
                    <xsl:value-of select="name()"/>
                    <xsl:text>=</xsl:text>  
                    <xsl:value-of select="."/>  
                    <xsl:if test="position()!=last()">&amp;</xsl:if>
                </xsl:for-each>
            </query>
        </result>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Hard to say if it's "dynamic/generic" enough.