2

I need to transform an xml-structure into a text string using xslt. I have a xml structure like this:

<index>
  <account index="0">00000000000</account>
  <customerId index="0">1112xxxxxxx</customerId>
  <authorization>1</authorization>
  <access>1</access>
  <documentGroup>1</documentGroup>
  <documentType>165200</documentType>
  <!-- Any number of child nodes -->
</index>

I need to transform this as post-parameters like this:

account=00000000000&customerId=1112xxxxxxx&authorization=1.....

Any ideas on how to achieve this?

0

3 Answers 3

3

Note that if you are not limited to XSLT 1.0, you can use extended XSLT 2.0 xsl:value-of and reduce all to a single template:

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

    <xsl:template match="index">
        <xsl:value-of select="*/concat(local-name(),'=',.)" separator="&amp;"/>
    </xsl:template>

</xsl:stylesheet>

Even in XSLT 1.0 you can reduce everything to single template, without the needing to adopt any iteration instruction:

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

    <xsl:template match="index/*">
        <xsl:if test="position()>1">
            <xsl:text>&amp;</xsl:text>
        </xsl:if>
        <xsl:value-of select="concat(local-name(), '=', .)"/>
    </xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

4 Comments

This is the best solution of all three and much better than the accepted answer. +1.
Thanks @Dimitre, you cheered me up.
Cool :-), +1 from me as well.
This answer came after accepting the solution from actionshrimp, but of course I will set this as the accepted solution :) Thanks to all contributors!
1

Something like this should do what you need. You might need to watch out for entity encoding with the &amp; though, but xsl:output method="text"should take care of this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <xsl:output method="text"/>  
   <xsl:template match="index">
       <xsl:variable name="len" select="count(*)"/>
       <xsl:for-each select="*">
            <xsl:value-of select="name()"/>=<xsl:value-of select="."/><xsl:choose>
                <xsl:when test="position() &lt; $len">&amp;</xsl:when>
            </xsl:choose>
       </xsl:for-each>
   </xsl:template>
</xsl:stylesheet>

This will not 'escape' the strings though (i.e. convert things like spaces into %20), which might cause you issues, but will work for any number of child nodes which I think was the main problem you were facing?

2 Comments

Great! Thanks a lot, that worked beautifully :) The only change I did was to use local-name() instead of name() to get rid of any namespace prefixes if present.
But @_erik: But see and consider accepting the much better solution of @empo.
0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" indent="yes"/>

    <xsl:template match="index">
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:value-of select="concat(local-name(), '=', .)"/>
        <xsl:if test="following-sibling::*">
            <xsl:text>&amp;</xsl:text>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.