XSLT 2.0: обработка вложенных XSD - PullRequest
1 голос
/ 28 марта 2011

Мне нужно собрать несколько XSD с (неуказанным) числом вложенных импортов во временную переменную дерева. Преобразование начинается с schema_1.xsd, который, в свою очередь, импортирует несколько других XSD.

Как это: содержание schema_1.xsd:

<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd">
  <import namespace="http://www.someplace.com" schemaLocation="schema_2.xsd"/>
  <import namespace="http://www.someplace.com" schemaLocation="schema_3.xsd"/>
  <element name="TopElement1">
    <complexType>
      <sequence>
        <element name="ChildElement1"/>
        <element name="ChildElement2"/>
        <element name="ChildElement3"/>
      </sequence>
    </complexType>
  </element>
</schema>

и содержимое schema_2.xsd:

<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd">
  <import namespace="http://www.someplace.com" schemaLocation="schema_3.xsd"/>
  <import namespace="http://www.someplace.com" schemaLocation="schema_4.xsd"/>
  <element name="TopElement2">
    <complexType>
      <sequence>
        <element name="ChildElement4" minOccurs="0"/>
        <element name="ChildElement5"/>
      </sequence>
    </complexType>
  </element>
</schema>

и так далее (я полагаю, включение третьего XSD немного излишне?).

Что мне нужно сделать, так это построить целое временное дерево, содержащее все узлы всех вложенных XSD, включая содержимое первого XSD, т.е. schema_1.xsd. Как видно из XSD, некоторые операции импорта могут происходить дважды. Предпочтительно любая схема должна быть скопирована в нужную переменную только один раз. Что еще хуже, я знаю, что могут быть циклические ссылки, которые явно накладывают дополнительные ограничения на пространство решений.

Мне нужно, чтобы результирующее временное дерево было доступно в переменной в XSLT. Возможно, так:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:variable name="root">
    <!-- magic -->
  </xsl:variable>
  <xsl:template match="/">
    <!-- processing $root/fullStructure --> 
  </xsl:template>
</xsl:stylesheet>

Фактическое содержимое $ root. Я бы хотел выглядеть примерно так:

<fullStructure>
  <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd">
    <import namespace="http://www.someplace.com" schemaLocation="schema_2.xsd"/>
    <import namespace="http://www.someplace.com" schemaLocation="schema_3.xsd"/>
    <element name="TopElement1">
      <complexType>
        <sequence>
          <element name="ChildElement1"/>
          <element name="ChildElement2"/>
          <element name="ChildElement3"/>
        </sequence>
      </complexType>
    </element>
  </schema>
  <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd">
    <import namespace="http://www.someplace.com" schemaLocation="schema_3.xsd"/>
    <import namespace="http://www.someplace.com" schemaLocation="schema_4.xsd"/>
    <element name="TopElement2">
      <complexType>
        <sequence>
          <element name="ChildElement4" minOccurs="0"/>
          <element name="ChildElement5"/>
        </sequence>
      </complexType>
    </element>
  </schema>
  <!-- copy-of for schema_3.xsd and schema_4.xsd is omitted for the sake of brevity. -->
</fullStructure>

Размер этого дерева ограничен только количеством импорта и доступными вычислительными ресурсами. Конечно, узлы импорта больше не нужны, однако, они также не представляют проблемы, так что скрытая копия полностью в порядке.

Основное обновление

По просьбе Дмитрия Новатчева, я включил пару действительных XSD, а также описание желаемого результата. Кроме того, я удалил некоторые лишние замечания. Я также сделал несколько небольших обновлений из-за отзывов от LarsH.

Может кто-нибудь дать мне указатель в правильном направлении? Спасибо миллион!

1 Ответ

2 голосов
/ 30 марта 2011

Эта таблица стилей:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:local="http://localhost"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 exclude-result-prefixes="local xs">
    <xsl:template match="/">
        <fullStructure>
            <xsl:copy-of select="local:explode(.)"/>
        </fullStructure>
    </xsl:template>
    <xsl:function name="local:explode" as="node()*">
        <xsl:param name="pNodes" as="node()*"/>
        <xsl:sequence select="local:explode($pNodes/root(.),())"/>
    </xsl:function>
    <xsl:function name="local:explode" as="node()*">
        <xsl:param name="pTodo" as="node()*"/>
        <xsl:param name="pDone" as="node()*"/>
        <xsl:sequence
             select="if (empty($pTodo))
                     then $pDone
                     else local:explode(
                             document(
                                ($pTodo except $pDone)
                                   /xs:schema/xs:import/@schemaLocation
                             ),
                             $pTodo | $pDone
                          )"/>
    </xsl:function>
</xsl:stylesheet>

С этим вводом:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd">
    <import namespace="http://www.someplace.com"
            schemaLocation="schema2.xsd"/>
    <element name="TopElement1">
        <complexType>
            <sequence>
                <element name="ChildElement1"/>
                <element name="ChildElement2"/>
                <element name="ChildElement3"/>
            </sequence>
        </complexType>
    </element>
</schema>

И этот schema2.xsd документ:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd">
    <element name="TopElement2">
        <complexType>
            <sequence>
                <element name="ChildElement4" minOccurs="0"/>
                <element name="ChildElement5"/>
            </sequence>
        </complexType>
    </element>
</schema>

Вывод:

<fullStructure>
    <schema xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd">
        <import namespace="http://www.someplace.com"
                schemaLocation="schema2.xsd"/>
        <element name="TopElement1">
            <complexType>
                <sequence>
                    <element name="ChildElement1"/>
                    <element name="ChildElement2"/>
                    <element name="ChildElement3"/>
                </sequence>
            </complexType>
        </element>
    </schema>
    <schema xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema.xsd">
        <element name="TopElement2">
            <complexType>
                <sequence>
                    <element name="ChildElement4" minOccurs="0"/>
                    <element name="ChildElement5"/>
                </sequence>
            </complexType>
        </element>
    </schema>
</fullStructure>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...