Объединить атрибуты xmlns с корневым элементом? - PullRequest
1 голос
/ 30 октября 2010

Я конвертирую набор XML-документов из одного формата, который не включает префиксы пространства имен, в другой, что делает. Все относительно просто, но в выводе XMLNS оно немного повторяется. Ниже приведен пример.

(очень простой) ввод XML

<?xml version="1.0"?>
<a/>

XSLT

<!-- xmlns="http://www.w3.org/1999/xhtml" -->

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"

    xmlns:a="urn:data.test-a"
    xmlns:b="urn:data.test-b"
    xmlns:c="urn:data.test-c"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:local.test schema/test.xsd"

    version="1.0">

    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/a">
        <xsl:element name="a:test-a">
            <!-- attempted fix -->
            <xsl:copy-of select="namespace::*"/>

            <!-- is there a better way to get this in there? -->
            <xsl:attribute name="xsi:schemaLocation">urn:local.test schema/test.xsd</xsl:attribute>

            <xsl:element name="b:test-b">
                <xsl:element name="c:test-c">content</xsl:element>
            </xsl:element>

        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

выход

<?xml version="1.0"?>
<a:test-a
    xmlns:a="urn:data.test-a"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:local.test schema/test.xsd">
  <b:test-b xmlns:b="urn:data.test-b">
    <c:test-c xmlns:c="urn:data.test-c">content</c:test-c>
    <c:test-c xmlns:c="urn:data.test-c">content</c:test-c>
  </b:test-b>
  <b:test-b xmlns:b="urn:data.test-b">
    <c:test-c xmlns:c="urn:data.test-c">content</c:test-c>
    <c:test-c xmlns:c="urn:data.test-c">content</c:test-c>
  </b:test-b>
</a:test-a>

Желаемый выход

<?xml version="1.0"?>
<a:test-a
    xmlns:a="urn:data.test-a"
    xmlns:b="urn:data.test-b"
    xmlns:c="urn:data.test-c"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:local.test schema/test.xsd">
  <b:test-b>
    <c:test-c>content</c:test-c>
    <c:test-c>content</c:test-c>
  </b:test-b>
  <b:test-b>
    <c:test-c>content</c:test-c>
    <c:test-c>content</c:test-c>
  </b:test-b>
</a:test-a>

По сути, я хочу объединить атрибуты пространства имен в корневой элемент. Я проводил некоторые исследования и думал, что запер это, используя, как видно здесь . Но это не дает желаемого эффекта; Я предполагаю, что либо использую его неправильно, либо ограничен возможностями xsltproc.

Выполнение второго прохода для очистки записей XMLNS также будет хорошим решением.

Кроме того, если это ограничивает решение, я думаю, что моя среда будет ограничена XSLT 1.0.

Спасибо за любые советы.

PS. Меньший вопрос: есть ли лучший способ получить этот атрибут schemaLocation в выводе, но это второстепенно.

1 Ответ

2 голосов
/ 30 октября 2010

Это, вероятно, самое короткое преобразование, удовлетворяющее вашим требованиям :

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

    xmlns:a="urn:data.test-a"
    xmlns:b="urn:data.test-b"
    xmlns:c="urn:data.test-c"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:local.test schema/test.xsd">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="a">
        <a:test-a xmlns:a="urn:data.test-a"
           xmlns:b="urn:data.test-b"
           xmlns:c="urn:data.test-c"
           xsi:schemaLocation="urn:local.test schema/test.xsd">
            <b:test-b>
                <c:test-c>content</c:test-c>
            </b:test-b>
        </a:test-a>
    </xsl:template>
</xsl:stylesheet>

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

<a/>

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

<a:test-a xmlns:a="urn:data.test-a"
   xmlns:b="urn:data.test-b"
   xmlns:c="urn:data.test-c"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="urn:local.test schema/test.xsd">
   <b:test-b>
      <c:test-c>content</c:test-c>
   </b:test-b>
</a:test-a>

Однако, имейте в виду : Размещение всех узлов пространства имен в верхнем элементе, даже если они там не нужны, не рекомендуется, поскольку все узлы пространства имен копируются во все дочерние элементы, и это приводит тратить много памяти.

...