http://qs321.pair.com?node_id=238962

jptxs has asked for the wisdom of the Perl Monks concerning the following question:

I've RTFMed and STFW for hours now. What started out as a silly distraction while on vacation has now driven me close to insane. I downloaded a tutorial about XML/XSLT/XPath to play with while on vacation from work. It had me use JEdit to do stuff, but I figgered I'd try the same exercise in perl. So after a very long wait having typed perl -MCPAN -e 'install Bundle::XML' I set out to use XML::XSLT to do the job. My first crack at the code was straight off the man page (current is more complex). What that code did (and continues to do) was simply print out the HTML from my xsl file with no content. It appears that it simply ignores the contents of the xml file. The code I wrote first is long gone. I have copy and pasted five different things off the web (some straight from tutorials) that are supposed to work and seem to simply not work for me (aside from printing empty HTML tables). The code below has some wacky stuff in it I've put in to help me see what's happening, too.

I'm absolutely stumped. I'm running this on Debian(Woody) with perl 5.6.1 and XML::XSLT .40. The xsl and xml(wsdl) files are from the tutorial this started with and work as is when I use JEdit's XSLT processor. I knew XML::XSLT was not a 1.0 module when I started out, but I've now found SO many people doing exactly this with no issues I can't believe it just doesn't work. *sigh* Any help appreciated.

the perl:

#!/usr/bin/perl -w use strict; use XML::XSLT; my $xslfile = 'soap.xsl'; my $xmlfile = 'query.wsdl'; #my $parser = XML::XSLT->new (SOURCE => $xslfile); #print $parser->serve (SOURCE => $xmlfile); my $xslt = XML::XSLT->new ($xslfile, warnings => 1); open ( XML, "$xmlfile" ) or die "$! -- $?\n"; my $stuff = join "", <XML>; close(XML); print "$stuff\n"; $xslt->transform ($stuff); print "Content-type: text/html\n\n"; print $xslt->toString; $xslt->dispose;

the xsl:

<?xml version="1.0" encoding="UTF-8"?> <!-- Soap.xsl by Ammai.com. WSDL Analyzer for SOAP RPC Web + Services. January 2003. --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/T +ransform"> <xsl:template match="/"> <html> <head> <style type="text/css"> th { background: #FFD7C1; } td { background: #FAF0E6; } </style> <title>WSDL Analyzer</title> </head> <body> <table border="1"> <tr> <th><xsl:value-of select="//*[local-name()='se +rvice']/@name"/></th> </tr> <tr> <td>Endpoint: <i><xsl:value-of select="//*[loc +al-name()='service']/*[local-name()='port']/*[local-name()='address'] +/@location"/></i></td> </tr> <tr> <td>Description: <i><xsl:value-of select="//*[ +local-name()='service']/*[local-name()='documentation']"/></i></td> </tr> </table> <br/> <table border="1"> <tr> <th>Operations</th> </tr> <tr> <td><xsl:apply-templates select="//*[local-name()= +'portType']"/></td> </tr> </table> <xsl:for-each select="//*[local-name()='portType']/*[local-name()='ope +ration']"> <br/> <table border="1"> <tr> <th><xsl:value-of select="@name"/></th> </tr> <tr> <td> <i><u>Request:</u></i><br/> <xsl:call-template name="request"> <xsl:with-param name="input" select="./*[local +-name()='input']/@message"/> </xsl:call-template> <i><u>Response:</u></i><br/> <xsl:call-template name="response"> <xsl:with-param name="output" select="./*[loca +l-name()='output']/@message"/> </xsl:call-template> </td> </tr> </table> </xsl:for-each> </body> </html> </xsl:template> <xsl:template match="//*[local-name()='portType']"> <xsl:for-each select="./*[local-name()='operation']"> <xsl:value-of select="@name"/> <br/> </xsl:for-each> </xsl:template> <xsl:template name="request"> <xsl:param name="input"/> <xsl:for-each select="//*[local-name()='message'][contains($input, @n +ame)]/*[local-name()='part']"> <xsl:value-of select="@name"/> <xsl:text> : </xsl:text> <xsl:value-of select="@type"/> <br/> </xsl:for-each> </xsl:template> <xsl:template name="response"> <xsl:param name="output"/> <xsl:for-each select="//*[local-name()='message'][contains($output, @n +ame)]/*[local-name()='part']"> <xsl:value-of select="@name"/> <xsl:text> : </xsl:text> <xsl:value-of select="@type"/> <br/> </xsl:for-each> </xsl:template> </xsl:stylesheet>

the xml:

<?xml version="1.0" encoding="UTF-8"?> <definitions name="XMethodsQuery" targetNamespace="http://www.xmethods +.net/interfaces/query.wsdl" xmlns:tns="http://www.xmethods.net/interf +aces/query.wsdl" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" x +mlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://sch +emas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.o +rg/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="ht +tp://www.xmethods.net/interfaces/query.xsd" targetNamespace="http://w +ww.xmethods.net/interfaces/query.xsd"> <complexType name="ServiceSummary"> <sequence> <element name="name" nillable="true" type="xsd:str +ing"/> <element name="id" nillable="true" type="xsd:strin +g"/> <element name="shortDescription" nillable="true" t +ype="xsd:string"/> <element name="wsdlURL" nillable="true" type="xsd: +string"/> <element name="publisherID" nillable="true" type=" +xsd:string"/> </sequence> </complexType> <complexType name="ArrayOfServiceSummary"> <complexContent> <restriction base="soapenc:Array"> <attribute ref="soapenc:arrayType" wsdl:arrayT +ype="tns:ServiceSummary[]"/> </restriction> </complexContent> </complexType> <complexType name="IDNamePair"> <sequence> <element name="id" nillable="true" type="xsd:strin +g"/> <element name="name" nillable="true" type="xsd:str +ing"/> </sequence> </complexType> <complexType name="ArrayOfIDNamePair"> <complexContent> <restriction base="soapenc:Array"> <attribute ref="soapenc:arrayType" wsdl:arrayT +ype="tns:IDNamePair[]"/> </restriction> </complexContent> </complexType> <complexType name="ServiceDetail"> <sequence> <element name="name" nillable="true" type="xsd:str +ing"/> <element name="id" nillable="true" type="xsd:strin +g"/> <element name="shortDescription" nillable="true" t +ype="xsd:string"/> <element name="description" nillable="true" type=" +xsd:string"/> <element name="implementationID" nillable="true" t +ype="xsd:string"/> <element name="email" nillable="true" type="xsd:st +ring"/> <element name="wsdlURL" nillable="true" type="xsd: +string"/> <element name="infoURL" nillable="true" type="xsd: +string"/> <element name="discussionURL" nillable="true" type +="xsd:string"/> <element name="notes" nillable="true" type="xsd:st +ring"/> <element name="tmodelID" nillable="true" type="xsd +:string"/> <element name="publisherID" nillable="true" type=" +xsd:string"/> <element name="uuid" nillable="true" type="xsd:str +ing"/> </sequence> </complexType> </schema> </types> <message name="getServiceSummariesByPublisher0SoapIn"> <part name="publisherID" type="xsd:string"/> </message> <message name="getServiceSummariesByPublisher0SoapOut"> <part name="Result" xmlns:ns1="http://www.xmethods.net/interfa +ces/query.xsd" type="ns1:ArrayOfServiceSummary"/> </message> <message name="getAllServiceSummaries1SoapIn"/> <message name="getAllServiceSummaries1SoapOut"> <part name="Result" xmlns:ns1="http://www.xmethods.net/interfa +ces/query.xsd" type="ns1:ArrayOfServiceSummary"/> </message> <message name="getAllServiceNames2SoapIn"/> <message name="getAllServiceNames2SoapOut"> <part name="Result" xmlns:ns1="http://www.xmethods.net/interfa +ces/query.xsd" type="ns1:ArrayOfIDNamePair"/> </message> <message name="getServiceNamesByPublisher3SoapIn"> <part name="publisherID" type="xsd:string"/> </message> <message name="getServiceNamesByPublisher3SoapOut"> <part name="Result" xmlns:ns1="http://www.xmethods.net/interfa +ces/query.xsd" type="ns1:ArrayOfIDNamePair"/> </message> <message name="getServiceDetail4SoapIn"> <part name="id" type="xsd:string"/> </message> <message name="getServiceDetail4SoapOut"> <part name="Result" xmlns:ns1="http://www.xmethods.net/interfa +ces/query.xsd" type="ns1:ServiceDetail"/> </message> <portType name="XMethodsQuerySoapPortType"> <operation name="getServiceSummariesByPublisher" parameterOrde +r="publisherID"> <input name="getServiceSummariesByPublisher0SoapIn" messag +e="tns:getServiceSummariesByPublisher0SoapIn"/> <output name="getServiceSummariesByPublisher0SoapOut" mess +age="tns:getServiceSummariesByPublisher0SoapOut"/> </operation> <operation name="getAllServiceSummaries" parameterOrder=""> <input name="getAllServiceSummaries1SoapIn" message="tns:g +etAllServiceSummaries1SoapIn"/> <output name="getAllServiceSummaries1SoapOut" message="tns +:getAllServiceSummaries1SoapOut"/> </operation> <operation name="getAllServiceNames" parameterOrder=""> <input name="getAllServiceNames2SoapIn" message="tns:getAl +lServiceNames2SoapIn"/> <output name="getAllServiceNames2SoapOut" message="tns:get +AllServiceNames2SoapOut"/> </operation> <operation name="getServiceNamesByPublisher" parameterOrder="p +ublisherID"> <input name="getServiceNamesByPublisher3SoapIn" message="t +ns:getServiceNamesByPublisher3SoapIn"/> <output name="getServiceNamesByPublisher3SoapOut" message= +"tns:getServiceNamesByPublisher3SoapOut"/> </operation> <operation name="getServiceDetail" parameterOrder="id"> <input name="getServiceDetail4SoapIn" message="tns:getServ +iceDetail4SoapIn"/> <output name="getServiceDetail4SoapOut" message="tns:getSe +rviceDetail4SoapOut"/> </operation> </portType> <binding name="XMethodsQuerySoap" type="tns:XMethodsQuerySoapPortT +ype"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.or +g/soap/http"/> <operation name="getServiceSummariesByPublisher"> <soap:operation soapAction="" style="rpc"/> <input name="getServiceSummariesByPublisher0SoapIn"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </input> <output name="getServiceSummariesByPublisher0SoapOut"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </output> </operation> <operation name="getAllServiceSummaries"> <soap:operation soapAction="" style="rpc"/> <input name="getAllServiceSummaries1SoapIn"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </input> <output name="getAllServiceSummaries1SoapOut"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </output> </operation> <operation name="getAllServiceNames"> <soap:operation soapAction="" style="rpc"/> <input name="getAllServiceNames2SoapIn"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </input> <output name="getAllServiceNames2SoapOut"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </output> </operation> <operation name="getServiceNamesByPublisher"> <soap:operation soapAction="" style="rpc"/> <input name="getServiceNamesByPublisher3SoapIn"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </input> <output name="getServiceNamesByPublisher3SoapOut"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </output> </operation> <operation name="getServiceDetail"> <soap:operation soapAction="" style="rpc"/> <input name="getServiceDetail4SoapIn"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </input> <output name="getServiceDetail4SoapOut"> <soap:body use="encoded" namespace="http://www.xmethod +s.net/interfaces/query" encodingStyle="http://schemas.xmlsoap.org/soa +p/encoding/"/> </output> </operation> </binding> <service name="XMethodsQuery"> <documentation>XMethods query service</documentation> <port name="XMethodsQuerySoap" binding="tns:XMethodsQuerySoap" +> <soap:address location="http://www.xmethods.net/interfaces +/query"/> </port> </service> </definitions>
We speak the way we breathe. --Fugazi

update (broquaint): added <readmore>

Replies are listed 'Best First'.
Re: XML::XSLT not transforming xml
by diotalevi (Canon) on Feb 27, 2003 at 03:32 UTC

    Your post is too large to do anything meaningful with. I did notice your dubious construction <xsl:value-of select="//*[local-name()='service']/*[local-name()='port']/*[local-name()='address']/@location"/>. You probably want to write that as <xsl:value-of select="//service/port/address/@location"/>. Your usage of local-name() is unusual.


    Seeking Green geeks in Minnesota

      And if I didn't post all the xml and xsl someone else would have complained that it wasn't there, right? =]

      Update: OK, changing that query worked. But why? Any why does it work in the other processor just fine? Now it works, but I'm more confused than ever...

      Anyway, I know nothing about this XML stuff. I'm trying to learn it. As I said in the original post, these files work fine using other XSLT processors. So as strange as the structure may be (and the tutorial that they came from even made a note to point out the local-name() structure), it seems to be OK according to other solutions.

      We speak the way we breathe. --Fugazi

        I didn't think of it until just now but the use of the prepended // also imposes a performance penalty on your code. If you can specify it as a rooted element that's a win.


        Seeking Green geeks in Minnesota

Re: XML::XSLT not transforming xml
by petesmiley (Friar) on Feb 27, 2003 at 15:59 UTC
    Hmm, actually I've had nothing but problems with XML::XSLT myself. I find it to be just a wee bit unfinished for the XSL I use. I recommend Sablotron. It seems to be pretty complete and works under winbloze and unix.

      BTW the XML::XSLT project is always looking for new developers - please drop by the Sourceforge page or e-mail me if you would like to volunteer

      /J\