Объединить две XML-схемы, используя XSLT - PullRequest
1 голос
/ 20 мая 2010

Я преобразую XML-схему, используя XSLT 2.0. Первая схема (s1.xsd) импортирует вторую схему (s2.xsd) следующим образом:

Содержимое s1.xsd

<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd"
    xmlns:ns1="URI1" targetNamespace="URI2" 
    elementFormDefault="qualified" attributeFormDefault="unqualified">
    <import namespace="URI1" schemaLocation="s2.xsd"/>
    <element name="element1"/>
    <element name="element2"/>
</schema>

и содержание s2.xsd

<schema xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:ns1="URI1" targetNamespace="URI1">
    <attribute name="attr1"/>
<schema>

Мой XSLT объявляет пространство имен XS следующим образом:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">  

Я хотел бы объединить узлы s2.xsd в -элемент s1.xsd. Пока я пробовал

<xsl:template name="merge_imported_schemas">
    <xsl:for-each select="/schema/import[@namespace = //namespace::*]">
        <!-- file exists? -->
        <xsl:choose>
            <xsl:when test="boolean(document(@schemaLocation))">
                <!-- schema found -->
                <xsl:copy-of select="document(@schemaLocation)/*/node()"/>
            </xsl:when>
            <xsl:otherwise>
                <!-- schema not found -->
                <xsl:message terminate="yes">
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:template>

но я не получаю желаемого результата. Может ли кто-нибудь сказать мне, что я делаю не так? Я подозреваю, что здесь происходит столкновение пространства имен, но, честно говоря, использование пространств имен немного сбивает с толку. Спасибо!

1 Ответ

2 голосов
/ 20 мая 2010

Вы должны квалифицировать элементы в вашем XPath. На данный момент select="/schema/import[@namespace = //namespace::*]"> вообще ничего не соответствует, потому что нет элемента /schema. XPath пытается сопоставить элементы с пространством имен no .

Измените его на select="/xs:schema/xs:import[@namespace = //namespace::*]">, и оно должно работать.

Помните, префиксы пространства имен являются псевдонимом для URI пространства имен, и если у вас есть пространство имен по умолчанию (как в ваших файлах xsd), элементы без префикса по-прежнему будут квалифицированы для пространства имен.

Кроме того, вместо <xsl:for-each select="/schema/import[@namespace = //namespace::*]"> вы можете добиться большего успеха, используя <xsl:apply-templates select="/xs:schema/node()" и определяя различные шаблоны для разных типов узлов, которые вы хотите скопировать в выходное дерево.

...