1

I am trying to process an XML file with XSLT to produce a list or table or (eventually) an SQL INSERT command with some of the values. I have been using the example from w3schools http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog.

My XML is very simple and I need to extract just the name and the rate of the hotel:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <getHotelsResponse xmlns="http://hotel.booking.vbooking.com">
      <getHotelsReturn>
        <address>
          <number>589-591</number>
          <postcode>08014</postcode>
          <region>Catalonia</region>
          <street>Carrer Vermell</street>
          <town>Barcelona</town>
        </address>
        <name>Downtown Hotel</name>
        <rate>235.0</rate>
      </getHotelsReturn>
    </getHotelsResponse>
  </soapenv:Body>
</soapenv:Envelope>

The best XSLT I could build up from the w3schools was this one:

<?xml version="1.0" encoding="utf-8"?>
<!-- Edited by XMLSpyΠ-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/soapenv:Envelope/soapenv:Body/getHotelsResponse">
  <html>
  <body>
  <h2>Hotels in Barcelona</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Hotel name</th>
        <th>Rate ($/night)</th>
      </tr>
      <xsl:for-each select="getHotelsReturn">
      <tr>
        <td><xsl:value-of select="name"/></td>
        <td><xsl:value-of select="rate"/></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

Which should produce a similar result to what I had in the w3schools example, but it comes back as blank.

Can anyone please explain this? Thanks.

keshlam
  • 7,931
  • 2
  • 19
  • 33
Ariestar
  • 35
  • 2
  • 6
  • 1
    Note the default-namespace binding on your input's `` element. You need to make that explicit in the XSLT -- set up a prefix for that URI and use the prefix in the match expression. – keshlam Feb 06 '14 at 15:34
  • Can you please be a bit more specific, I am quite new to xslt and I am trying to get my head around namespaces – Ariestar Feb 06 '14 at 15:36
  • I'll try to make time to write a proper answer later today if someone else doesn't do it. – keshlam Feb 06 '14 at 15:37
  • Thank you, appreciate your time – Ariestar Feb 06 '14 at 15:39

2 Answers2

3

As pointed out by @keshlam, if elements in your input XML have namespaces, you must declare them in your XSLT stylesheet as well.

Find more detail on namespaces in a previous answer of mine.

The gist of the information you find there is: as far as the XSLT processor is concerned, a getHotelsReturn element is entirely different from a vb:getHotelsReturn element.

Stylesheet

<?xml version="1.0" encoding="utf-8"?>
<!-- Edited by XMLSpy?-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:vb="http://hotel.booking.vbooking.com"
   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
   exclude-result-prefixes="soapenv vb">

<xsl:template match="/soapenv:Envelope/soapenv:Body/vb:getHotelsResponse">
  <html>
  <body>
  <h2>Hotels in Barcelona</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Hotel name</th>
        <th>Rate ($/night)</th>
      </tr>
      <xsl:for-each select="vb:getHotelsReturn">
      <tr>
        <td><xsl:value-of select="vb:name"/></td>
        <td><xsl:value-of select="vb:rate"/></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

Output

<html>
   <body>
      <h2>Hotels in Barcelona</h2>
      <table border="1">
         <tr bgcolor="#9acd32">
            <th>Hotel name</th>
            <th>Rate ($/night)</th>
         </tr>
         <tr>
            <td>Downtown Hotel</td>
            <td>235.0</td>
         </tr>
      </table>
   </body>
</html>

Rendered HTML

enter image description here

Community
  • 1
  • 1
Mathias Müller
  • 22,203
  • 13
  • 58
  • 75
-3

You can use XPaths like this:

/Product1/Product2/Product3[@ValidYN = 'Y' and @ProductType = 'ABC']
/Product1/Product2/Product3[@ValidYN = 'Y' and @ProductType = 'DEF']
/Product1/Product2/Product3[@ValidYN = 'Y' and @ProductType = 'GHI']

Check this other question How to parse XML using XSLT?

Community
  • 1
  • 1
focusoft
  • 82
  • 1
  • 10