Как обрабатывать XML с пространствами имен?

#xml #xslt #xml-namespaces

#xml #xslt #xml-пространства имен

Вопрос:

Если у меня есть этот xml:

 <?xml version="1.0" encoding="UTF-8"?>
<env:Envelope>
<m:RgWsPublicFirmActRtUser>
      <m:firmActDescr>ΑΛΛΟ ΛΙΑΝΙΚΟ ΕΜΠΟΡΙΟ ΣΕ ΜΗ ΕΞΕΙΔΙΚΕΥΜΕΝΑ ΚΑΤΑΣΤΗΜΑΤΑ</m:firmActDescr>
      <m:firmActKind>2</m:firmActKind>
      <m:firmActKindDescr>ΔΕΥΤΕΡΕΥΟΥΣΑ</m:firmActKindDescr>
      <m:firmActCode>47191000</m:firmActCode>
   </m:RgWsPublicFirmActRtUser>

   <m:RgWsPublicFirmActRtUser>
      <m:firmActDescr>ΛΙΑΝΙΚΟ ΕΜΠΟΡΙΟ ΕΙΔΩΝ ΔΩΡΩΝ ΓΕΝΙΚΑ</m:firmActDescr>
      <m:firmActKind>2</m:firmActKind>
      <m:firmActKindDescr>ΔΕΥΤΕΡΕΥΟΥΣΑ</m:firmActKindDescr>
      <m:firmActCode>47191008</m:firmActCode>
   </m:RgWsPublicFirmActRtUser>
</env:Envelope>
 

И я использую этот XSLT:

 <?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
  <body>
  <h3>Δραστηριότητες</h3>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th style="text-align:left">Δραστηριότητα</th>
        <th style="text-align:left">Αριθμός δραστηριότητας</th>
        <th style="text-align:left">Περιγραφή δραστηριότητας</th>
        <th style="text-align:left">Κωδικός δραστηριότητας</th>
      </tr>
      <xsl:for-each select="Envelope/RgWsPublicFirmActRtUser">
      <tr>
        <td><xsl:value-of select="firmActDescr"/></td>
        <td><xsl:value-of select="firmActKind"/></td>
        <td><xsl:value-of select="firmActKindDescr"/></td>
        <td><xsl:value-of select="firmActCode"/></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>
 

Все работает нормально, но когда у меня есть пространство имен во входном XML:

 <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m="http://gr/gsis/rgwspublic/RgWsPublic.wsdl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 

Вместо без пространств имен:

 <env:Envelope> 
 

XSLT не будет работать

Моя проблема в том, что XML получен от третьей стороны, и я не могу контролировать содержимое. Мне нужно обработать его как есть. Может быть, я могу заменить большой env:Envelope и маленький env:Envelope внутри серверного процесса, но могу ли я заставить XSLT работать без изменения XML?

Ответ №1:

Чтобы сопоставить элементы пространства имен в XSLT, вы должны объявить префикс пространства имен в таблице стилей для того же URI пространства имен и использовать этот префикс в ваших выражениях XPath:

 <?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:m="http://gr/gsis/rgwspublic/RgWsPublic.wsdl">

  <xsl:template match="/">
    <!-- ... -->
    <xsl:for-each select="env:Envelope/m:RgWsPublicFirmActRtUser">
 

( m: URI пространства имен взят из вашего комментария). URI пространства имен не обязательно должны быть реальными URL-адресами, которые может получить браузер, они просто обрабатываются как уникальные идентификаторы для пространства имен. Некоторые технологии XML используют идентификаторы «URN» для своих пространств имен (например urn:example:namespace ) вместо URL-адресов http.

Комментарии:

1. url-адрес m <m:rgWsPublicAfmMethodResponse xmlns:m=» gr/ gsis/rgwspublic/RgWsPublic.wsdl «> но странно, что я не могу найти этот тип URL-адреса url