1

i want to print each "string" node as a li item from the following xml:

<soapenv:Envelope 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soapenv="http://schemas.url.org/url/envelope/"
>
    <soapenv:Header>
        <MultiSpeakMsgHeader 
            Version="" UserID="" 
            Pwd="" AppName="xx" AppVersion="x" 
            Company="xxx" xmlns="http://www.url.org/Version_3.0"
        />
    </soapenv:Header>
    <soapenv:Body>
        <GetMethodsResponse xmlns="http://www.url.org/Version_3.0">
            <GetMethods>
                <string>GetDomainMembers</string>
                <string>GetDomainNames</string>
                <string>GetMethods</string>
                <string>pingURL</string>
                <string>GetAllMeters</string>
                <string>GetAllServiceLocations</string>
                <string>GetAllCustomers</string>
                <string>GetCustomerByCustId</string>
                <string>GetServiceLocationByAccountNo</string>
                <string>GetServiceLocationByMeterNo</string>
                <string>ReadingChangedNotification</string>
            </GetMethods>
        </GetMethodsResponse>
    </soapenv:Body>
</soapenv:Envelope>

i currently have the following xsl code -

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exslt="http://exslt.org/common"
>
    <xsl:output method="html" />

    <xsl:template match="/GetMethods">
        <ul>
            <xsl:for-each select="GetMethods/string">
                <li>
                    <xsl:value-of select="string"/><br/>
                </li>
            </xsl:for-each>    
        </ul>
    </xsl:template>
</xsl:stylesheet>

but all this does is prints each string node as a long line with no list formatting. any help would be appreciated.

i want this simple output:

    <ul>
        <li>GetDomainMembers</li>
        <li>GetDomainNames</li>
        <li>GetMethods</li>
        <li>pingURL</li>
        <li>GetAllMeters</li>
        <li>GetAllServiceLocations</li>
        <li>GetAllCustomers</li>
        <li>GetCustomerByCustId</li>
        <li>GetServiceLocationByAccountNo</li>
        <li>GetServiceLocationByMeterNo</li>
        <li>ReadingChangedNotification</li>
    </ul>

i'm currently getting this output (there is no formatting):

                                          GetDomainMembers            GetDomainNames            GetMethods            pingURL            GetAllMeters            GetAllServiceLocations            GetAllCustomers            GetCustomerByCustId            GetServiceLocationByAccountNo            GetServiceLocationByMeterNo            ReadingChangedNotification                  
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Please show the XML input you are actually using, and the output you are actually getting... your description of it is unclear, and there are multiple incompatibilities between both of them and the XSLT you showed. Are you using XSLT 2.0 and xpath-default-namespace? Please show your `` start tag and its attributes and namespace declarations. – LarsH Jan 09 '13 at 19:16
  • 1
    i've updated the code per your instructions - thanks. – user1822065 Jan 09 '13 at 19:30

2 Answers2

2
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exslt="http://exslt.org/common"
    xmlns:response="http://www.url.org/Version_3.0"
    exclude-result-prefixes="exslt response"
>
    <xsl:output method="html" />

    <xsl:template match="/">
        <xsl:apply-templates select="//response:GetMethods" />
    </xsl:template>

    <xsl:template match="response:GetMethods">
        <ul>
            <xsl:apply-templates select="response:string" />
        </ul>
    </xsl:template>

    <xsl:template match="response:string">
        <li>
            <xsl:value-of select="." />
        </li>
    </xsl:template>
</xsl:stylesheet>

Notes:

  • First we must make known the namespace that your response element is in. In your case the namespace URI is http://www.url.org/Version_3.0, which we need to assign to a prefix to make it usable in the XSLT. I chose to call that prefix response.
  • Next we need to control the output of the XSLT. This is easiest by matching the root node (<xsl:template match="/">) and defining where to go next by directly selecting //response:GetMethods for processing.
  • Templates for response:GetMethods and response:string define the rest of the transformation.
  • Lastly we must make sure that XML namespace prefixes do not show up in the resulting HTML. That's what exclude-result-prefixes does.
  • See it here: http://www.xmlplayground.com/kS1Cul
  • You can also read What are the differences between 'call-template' and 'apply-templates' in XSL? where I explained <xsl:apply-templates> a little closer.
  • In general you should avoid writing <xsl:for-each> and choose <xsl:apply-templates> instead.
Community
  • 1
  • 1
Tomalak
  • 332,285
  • 67
  • 532
  • 628
1

There is no element in your given input matching the pattern "/GetMethods". So your XML is probably being processed by the default template (though we don't know without seeing the rest of your XSLT). The default template outputs the text content of each element.

To fix this,

  1. Your match pattern shouldn't start with /, since GetMethods is not the top-level element. If you meant //GetMethods, that will match a <GetMethods> element (in no namespace) that occurs anywhere. But so will the pattern GetMethods; the // at the beginning is redundant.
  2. You need to specify the correct namespace for GetMethods. According to your input XML, GetMethods is in the namespace whose URI is http://www.test.org/Version_3.0. So you need to declare a namespace prefix for that namespace (e.g. "test") and use it in your match pattern:

_

 <xsl:template match="test:GetMethods"
      xmlns:test="http://www.test.org/Version_3.0">...

Actually it's probably more practical to move the namespace declaration (xmlns:test="...") to the top-level <xsl:stylesheet> element (if you don't have it already). Then the test prefix will be available anywhere in the stylesheet that you need it.

LarsH
  • 27,481
  • 8
  • 94
  • 152