XSLT 2.0:处理嵌套 XSD

发布于 2024-10-26 20:31:56 字数 3573 浏览 4 评论 0原文

我需要将多个具有(未指定)数量的嵌套导入的 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>

这棵树的大小仅受导入数量和可用计算资源的限制。当然,导入节点不再是真正必要的,但是,它们也不会造成问题,因此盲目复制是完全可以的。

主要更新

根据 Dimitre Novaatchev 的要求,我添加了几个有效的 XSD,以及所需结果的描述。另外,我删除了一些多余的言论。根据 LarsH 的反馈,我还做了一些小的更新。

有人能给我指出正确的方向吗?谢谢一百万!

I need to collect several XSDs with a (unspecified) number of nested imports into a temporary tree variable. The transformation starts at schema_1.xsd, which in turn imports several other XSDs.

Like this: content of 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>

and content of 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>

and so on (I guess including a third XSD is a little redundant?).

What I need to do is to construct an entire temporary tree containing all the nodes from all the nested XSDs, including the content of the first XSD, i.e schema_1.xsd. As can be seen from the XSDs, some imports may occur twice. Preferably, any schema should only be copied to the desired variable once. To make matters worse, I'm aware that there might be cyclic references, which clearly put further constraints on the solution space.

I need the resulting temporary tree to be accessible in a variable in the XSLT. Perhaps like so:

<?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>

The actual content of $root I'd like to look something like this:

<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>

The size of this tree is only limited by the number of imports and the computational resources available. Of course, the import nodes are not really necessary any more, however, they don't pose a problem either, so a blind copy-of is totally ok.

Major update

As requested by Dimitre Novatchev, I've included a couple of valid XSDs, as well as a description of the desired result. In addition, I've removed some superfluous remarks. I have also made some minor updates due to the feedback from LarsH.

Could anyone please give me a pointer in the right direction? Thanks a million!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

远昼 2024-11-02 20:31:56

此样式表:

<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>

This stylesheet:

<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>

With this input:

<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>

And this schema2.xsd document:

<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>

Output:

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文