gpt4 book ai didi

xml - 使用 XSLT 根据 XSD 转换 XML

转载 作者:数据小太阳 更新时间:2023-10-29 02:17:47 25 4
gpt4 key购买 nike

我想创建一个可以转换 XML 的 XSLT,以便在输出 XML(来自 XSLT)中排除所有未在 XSD 中定义的元素和属性。

假设您有这个 XSD。

<xs:element name="parent">
<xs:complexType>
<xs:sequence>
<xs:element name="keptElement1" />
<xs:element name="keptElement2" />
</xs:sequence>

<xs:attribute name="keptAttribute1" />
<xs:attribute name="keptAttribute2" />
</complexType>
</xsd:element>

你有这个输入 XML

<parent keptAttribute1="kept" 
keptAttribute2="kept"
notKeptAttribute3="not kept"
notKeptAttribute4="not kept">

<notKeptElement0>not kept</notKeptElement0>
<keptElement1>kept</keptElement1>
<keptElement2>kept</keptElement2>
<notKeptElement3>not kept</notKeptElement3>
</parent>

然后我希望输出的 Xml 看起来像这样。

<parent keptAttribute1="kept" 
keptAttribute2="kept">

<keptElement1>kept</keptElement1>
<keptElement2>kept</keptElement2>
</parent>

我可以通过指定元素来做到这一点,但这大约是我的 xslt 技能所能达到的范围。我通常对所有元素和所有属性执行此操作时遇到问题。

最佳答案

您在这里面临两个挑战:(1) 识别模式中声明的元素名称和属性集,以及本地声明的适当上下文信息,以及 (2) 编写 XSLT 以保留与这些名称或名称匹配的元素和属性-和上下文。

还有第三个问题,即明确说明“XSD 架构中定义(或未定义)的元素和属性”的含义。出于讨论的目的,我假设您指的是可以绑定(bind)到模式中的元素或属性声明的元素和属性,在验证情节 (a) Root 于输入文档树中的任意点,以及 (b) 以 a 开头顶级元素声明或属性声明。这个假设意味着几件事。 (a) 本地元素声明只会匹配上下文中的内容——在您的示例中,keptElement1keptElement2只有当它们是 parent 的 child 时才会保留,否则不会。 (b) 无法保证输入中的元素实际上会绑定(bind)到有问题的元素声明:如果它们的祖先之一在本地无效,那么在 XSD 1.0 和 1.1 中事情都会很快变得复杂。 (c) 我们不允许从命名类型定义开始验证;我们可以,但听起来好像这不是您感兴趣的内容。(d) 我们不允许从本地元素或属性声明开始验证。

有了这些明确的假设,我们就可以转向您的问题了。

第一个任务要求您列出 (a) 架构中具有顶级声明的所有元素和属性,以及 (b) 从它们可以访问的所有元素和属性。对于顶级声明,我们只需要记录对象(元素或属性)的种类和展开后的名称即可。对于本地对象,我们需要对象的种类和顶级元素声明的完整路径。对于您的示例架构,列表 (a) 包括

  • 元素{}父级

(我使用的惯例是在大括号中使用 namespace 名称编写扩展名称;有些人称此为 James Clark 的 Clark 表示法。)

列表(b)包括

  • 元素 {}parent/{}keptElement1
  • 元素 {}parent/{}keptElement2
  • 属性 {}parent/{}keptAttribute1
  • 属性 {}parent/{}keptAttribute2

在更复杂的模式中,在生成此列表的过程中会有一定数量的簿记。

您的第二个任务是编写一个 XSLT 样式表,将元素和属性保留在列表中并删除其余部分。 (我在这里假设当你放下一个元素时,你也会放下它的所有内容;你的问题谈论的是元素,而不是标签。)

对于列表中的每个元素,使用列表中给定的上下文编写适当的身份转换:

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

可以为每个元素写一个单独的模板,也可以将几个元素写到匹配模式中:

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

对于列表中的每个属性,执行相同的操作:

<xsl:template match="parent/@keptAttribute1">
<xsl:copy/>
</xsl:template>

覆盖元素和属性的默认模板,以抑制所有其他元素和属性:

<xsl:template match="*|@*"/>

[或者,如 DrMacro 所建议的,您可以在 XSLT 中编写一个函数或命名模板来查询您在任务 1 中生成的列表,而不是将其写出到具有显式匹配模式的重复模板中。根据您的背景,您可能会发现这种方法更容易或更难理解样式表的作用。]

关于xml - 使用 XSLT 根据 XSD 转换 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14833486/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com