Неиспользуемое объявление пространства имен появляется после XSLT - PullRequest
4 голосов
/ 30 сентября 2010

После поиска в сети ответов, поиска "почти" решений ... Я решил свести проблему к очень простому случаю.

Рассмотрим следующий фрагмент XML:

<me:root xmlns:me="http://stackoverflow.com/xml"
  xmlns="http://www.w3.org/1999/xhtml">
    <me:element>
        <p>Some HTML code here.</p>
    </me:element>
</me:root>

Обратите внимание, что элемент p относится к пространству имен XHTML, которое является стандартным для этого документа.

Теперь рассмотрим следующую простую таблицу стилей.Я хочу создать документ XHTML с содержанием me:element в качестве тела.

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:me="http://stackoverflow.com/xml"
  xmlns="http://www.w3.org/1999/xhtml"
  exclude-result-prefixes="me">
    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
                <title>My Title</title>
            </head>
            <body>
                <xsl:copy-of select="me:root/me:element/node()"/>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

Обратите внимание, что я включил exclude-result-prefixes ... Но посмотрите, что я получу:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>My Title</title>
    </head>
    <body>
        <p xmlns:me="http://stackoverflow.com/xml">Some HTML code here.</p>
    </body>
</html>

И что сводит меня с ума, вот почему, о, почему xmlns:me появляется внутри p элемента?

Независимо от того, что я пытался, я не мог заставить вещи работать.У меня странное ощущение, что проблема в моем xsl:copy-of утверждении.

1 Ответ

6 голосов
/ 30 сентября 2010

У меня странное ощущение, что проблема с моим xsl:copy-of заявление.

Именно в этом причина.

Исходный XML-документ содержит этот фрагмент :

<me:element> 
    <p>Some HTML code here.</p> 
</me:element> 

В модели данных XPath узлы пространства имен распространяются от корня поддерева до всех его потомков. Поэтому элемент <p> имеет следующие пространства имен:

  1. "http://www.w3.org/1999/xhtml"

  2. "http://stackoverflow.com/xml"

  3. "http://www.w3.org/XML/1998/namespace"

  4. http://www.w3.org/2000/xmlns/

Последние два зарезервированные пространства имен (для префиксов xml: и xmlns) и доступны для любого именованного узла.

Указанная проблема связана с тем, что по определению инструкция <xsl:copy-of> копирует все узлы и их полные поддеревья со всеми пространствами имен, принадлежащими каждому из узлов.

Помните : префиксы, указанные в качестве значения атрибута exclude-result-prefixes, исключаются только из элементов буквального результата !

Решение

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:me="http://stackoverflow.com/xml"
  xmlns="http://www.w3.org/1999/xhtml"
  exclude-result-prefixes="me">

  <xsl:output method="xml" omit-xml-declaration="yes"
  indent="yes"/>
  <xsl:strip-space elements="*"/>

    <xsl:template match="/">
     <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>My Title</title>
      </head>
      <body>
        <xsl:apply-templates select="me:root/me:element/*"/>
      </body>
     </html>
    </xsl:template>

    <xsl:template match="*">
      <xsl:element name="{name()}">
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
      </xsl:element>
    </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML :

<me:root xmlns:me="http://stackoverflow.com/xml"
  xmlns="http://www.w3.org/1999/xhtml">
    <me:element>
        <p>Some HTML code here.</p>
    </me:element>
</me:root>

желаемый, правильный результат выдается :

<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <title>My Title</title>
   </head>
   <body>
      <p>Some HTML code here.</p>
   </body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...