Как сохранить пространство имен XML в выводе XSLT? - PullRequest
2 голосов
/ 30 июня 2010

Таблица стилей XSL должна выводить следующий код в Internet Explorer:

<xml:namespace prefix="vml" ns="urn:schemas-microsoft-com:vml"/>

Но когда я выполняю следующий шаблон с любым XML

<xsl:template match="*|node()">
    <xml:namespace prefix="vml"
                   ns="urn:schemas-microsoft-com:vml"/>
</xsl:template>

IE выдает ошибку разбора: Таблица стилей не содержит элемент документа . В то же время Firefox удаляет xml пространство имен в выводе ...

Итак, как мне сохранить пространство имен xml в моих выходных данных?

Важно

а. Метод вывода, который я использую: html

б. Следующий код не решает мою проблему:

<xsl:template match="*|node()">
    <namespace prefix="vml"
               xmlns="http://www.w3.org/XML/1998/namespace"
               ns="urn:schemas-microsoft-com:vml"/>
</xsl:template>

Ответы [ 2 ]

2 голосов
/ 30 июня 2010

Нельзя использовать сохраненный префикс xml. Используйте что-то вроде этого:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dummy="dummy">
<xsl:namespace-alias stylesheet-prefix="dummy" result-prefix="xml"/>
<xsl:template match="/">
    <dummy:namespace prefix="vml"
                   ns="urn:schemas-microsoft-com:vml"/>
</xsl:template>
</xsl:stylesheet>

При любом вводе вы получите такой результат:

<xml:namespace prefix="vml" ns="urn:schemas-microsoft-com:vml" />
1 голос
/ 30 июня 2010

Если вы буквально хотите получить результат, как показано в вопросе, это очень просто: :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="/">
  <xml:namespace prefix="vml" ns="urn:schemas-microsoft-com:vml"/>
 </xsl:template>
</xsl:stylesheet>

Это преобразование при применении к любому документу XML (не используется), выдает желаемый результат :

<xml:namespace prefix="vml" ns="urn:schemas-microsoft-com:vml"/>

Однако мне кажется, что вы хотите добавить узел пространства имен к каждому элементу данного XML-документа (если это не так), просто дайте мне знать через комментарий, и я удалю этот ответ).

Если это так, вот простой и эффективный способ:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:vml="urn:schemas-microsoft-com:vml"
     exclude-result-prefixes="vml">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="vNamespace" select=
     "document('')/*/namespace::*[name()='vml']"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/*">
     <xsl:copy>
       <xsl:copy-of select="$vNamespace"/>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

применительно к любому документуНапример, этот :

<t>
    <a x="3">
        <b y="4"/>
    </a>
</t>

желаемый результат получается :

<t xmlns:vml="urn:schemas-microsoft-com:vml">
   <a x="3">
      <b y="4"/>
   </a>
</t>

Это может сбить с толку на первый взгляд , поскольку только верхний элемент результата имеет видимый узел пространства имен.Однако по определению (смотрите спецификацию пространства имен XML ), если элемент в корне (под) дерева имеет данный узел пространства имен, то все его дочерние элементы также имеютэтот узел пространства имен.Даже если вы скопируете пространство имен для каждого элемента, сериализатор XSLT удалит его из сериализованного (текстового) представления всех элементов, кроме верхнего.

В XSLT 2.0 вы можете просто использовать <xsl:namespace> инструкция :

<xsl:namespace name="vml" select="urn:schemas-microsoft-com:vml"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...