如何使用XSLT处理命名空间的XML文档?

时间:2014-02-06 15:30:35

标签: html sql xml parsing xslt

我正在尝试使用XSLT处理XML文件以生成列表或表或(最终)带有一些值的SQL INSERT命令。我一直在使用w3schools http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog的例子。

我的XML非常简单,我只需要提取酒店的名称和费率:

<?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>

我可以从w3schools建立的最好的XSLT就是这个:

<?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>

哪个应该产生与w3schools示例中的结果类似的结果,但它会以空白的形式返回。

有人可以解释一下吗?感谢。

2 个答案:

答案 0 :(得分:3)

正如@keshlam所指出的,如果输入XML中的元素具有名称空间,则必须在XSLT样式表中声明它们。

previous answer of mine中查找有关名称空间的更多详细信息。

您在其中找到的信息的要点是:就XSLT处理器而言,getHotelsReturn元素与vb:getHotelsReturn元素完全不同。

<强>样式表

<?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>

<强>输出

<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>

呈现HTML

  

enter image description here

答案 1 :(得分:-3)

你可以使用这样的XPath:

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

检查另一个问题How to parse XML using XSLT?