10

I have this XML document:

<ns0:getDataResponse xmlns:ns0="http://abc.com/">
    <return>
        <wrapper>
            <data><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
                            <ConDic>
                            <dictionary>bank</dictionary>
                                <rows>
                                    <row>
                                      <bic>ABKZKZKX</bic>
                                      <bcode>319</bcode>
                                      <name1>AA &quot;A BANK&quot;</namekz>
                                      <name2>BB &quot;B BANK&quot;</nameru>
                                    </row>
                                    <row>
                                      <bic>ABNAKZKX</bic>
                                      <bcode>922</bcode>
                                      <name1>CC &quot;C BANK&quot;</namekz>
                                      <name2>DD &quot;D BANK&quot;</nameru>
                                    </row>
                                </rows>
                            </ConDic>]]></data>
        </wrapper>
    </return>
</ns0:getDataResponse>

How I can parse it with XSL to get each rows in CDATA to make this kind of select:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://abc.com/">
<xsl:output method="html" />
<xsl:template match="text()|@*"/>
<xsl:template match="ns0:rows">

<select name="bank" id="bank" class="input" style="width: 370px;">
    <xsl:for-each select="row">
        <xsl:sort select="name1"/>
        <option value="{bic}"><xsl:value-of select="name1" /></option>
    </xsl:for-each>
</select>
6
  • 7
    Which XSLT processor do you use? You need an XSLT 3.0 processor with the 3.0 function w3.org/TR/2013/CR-xpath-functions-30-20130108/#func-parse-xml or you need an XSLT 1.0 or 2.0 processor supporting an extension function like saxonica.com/documentation/index.html#!functions/saxon/parse. Commented Sep 4, 2013 at 11:37
  • 1
    That escaped markup is not valid XML. There is no entity &quot; defined and there is no DTD references. Even if you used a first pass transform to extract the CDATA with disable-output-escaping, you would be left with invalid markup that won't parse as XML. Plus, it includes the XML declaration, which makes it more difficult to add a DTD reference in the DOE transform. Is there any way to get the producer of the webservice to change their output? Commented Sep 6, 2013 at 2:48
  • 1
    w3.org/TR/xml/#sec-predefined-ent defines quot so there does not have to be a DTD to define it. Commented Sep 14, 2013 at 14:42
  • @MartinHonnen, I think you should put your comment into an answer, so that this question is no longer in the "unanswered" category. Commented Oct 1, 2013 at 21:14
  • @Yoldar-Zi, does my comment help? Can you use a processor providing such an extension or providing XSLT 3.0 support? Commented Oct 2, 2013 at 9:46

2 Answers 2

1

As suggested in a comment, I post a solution. The example use XSLT 3.0 with Saxon 9.5 (needs PE or EE version):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns0="http://abc.com/"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math ns0"
    version="3.0">


    <xsl:output method="html" indent="yes"/>

    <xsl:template match="text()|@*"/>

    <xsl:template match="ns0:getDataResponse">

        <select name="bank" id="bank" class="input" style="width: 370px;">
            <xsl:for-each select="parse-xml(return/wrapper/data)//row">
                <xsl:sort select="name1"/>
                <option value="{bic}">
                    <xsl:value-of select="name1"/>
                </option>
            </xsl:for-each>
        </select>
    </xsl:template>

</xsl:stylesheet>

With an input of

<ns0:getDataResponse xmlns:ns0="http://abc.com/">
    <return>
        <wrapper>
            <data><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
                            <ConDic>
                            <dictionary>bank</dictionary>
                                <rows>
                                    <row>
                                      <bic>ABKZKZKX</bic>
                                      <bcode>319</bcode>
                                      <name1>AA &quot;A BANK&quot;</name1>
                                      <name2>BB &quot;B BANK&quot;</name2>
                                    </row>
                                    <row>
                                      <bic>ABNAKZKX</bic>
                                      <bcode>922</bcode>
                                      <name1>CC &quot;C BANK&quot;</name1>
                                      <name2>DD &quot;D BANK&quot;</name2>
                                    </row>
                                </rows>
                            </ConDic>]]></data>
        </wrapper>
    </return>
</ns0:getDataResponse>

the result is

<select name="bank" id="bank" class="input" style="width: 370px;">
   <option value="ABKZKZKX">AA "A BANK"</option>
   <option value="ABNAKZKX">CC "C BANK"</option></select>
Sign up to request clarification or add additional context in comments.

Comments

0

If you have the exslt extensions available, you should be able to use exslt:node-set to create a variable of the contents. Try something like (untested):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:exsl="http://exslt.org/common"
   extension-element-prefixes="exsl"
   exclude-result-prefixes="exsl"
   version="1.0">

<xsl:template match="/">
    <xsl:variable name="inner" select="exsl:node-set(//data/text())" />
    <select name="bank" id="bank" class="input" style="width: 370px;">
        <xsl:for-each select="$inner//row">
            ...
        </xsl:for-each>
    </select>
</xsl:template>

</xsl:stylesheet>

1 Comment

The node-set() function takes a result tree fragment and converts it to a node-set. It won't take a string and parse it into a node-set. So at best, the value of $inner will just be a string, and you won't be able to select $inner//row.

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.