【问题标题】:Only copy valid elements and attributes?只复制有效的元素和属性?
【发布时间】:2014-02-12 21:30:35
【问题描述】:

我正在尝试使用 XSLT 将一个 XML 文档转换为另一个 XML 文档。是否可以在样式表中指定我只想复制“有效”的元素/属性?有效是指它们存在于目标架构中。

例如,给定 source.xsd:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:more_emotion="http://example.org/more_emotion"
    targetNamespace="http://example.org/more_emotion"
    elementFormDefault="qualified" 
    attributeFormDefault="qualified">

    <xs:element name="Emotion" type="more_emotion:imComplex"/>
    <xs:complexType name="imComplex">
        <xs:sequence>
            <xs:element name="Joy" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element name="Anger" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element name="Confusion" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

还有destination.xsd:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://example.org/emotion"
    xmlns:emotion="http://example.org/emotion"
    elementFormDefault="qualified" 
    attributeFormDefault="qualified">

    <xs:element name="Emotion" type="emotion:imComplex"/>
    <xs:complexType name="imComplex">
        <xs:sequence>
            <xs:element name="Joy" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

而xml文档看起来是这样的

<?xml version="1.0" encoding="UTF-8"?>
<more_emotion:Emotion xmlns:more_emotion="http://example.org/more_emotion">
    <more_emotion:Joy>Hooray!</more_emotion:Joy>
    <more_emotion:Anger>Grrr</more_emotion:Anger>
    <more_emotion:Confusion>Huh?</more_emotion:Confusion>
</more_emotion:Emotion>

是否可以使用 XSLT 将文档转换为以下而无需不必命名要复制或排除的特定元素/属性?

<?xml version="1.0" encoding="UTF-8"?>
<more_emotion:Emotion xmlns:more_emotion="http://example.org/more_emotion">
    <more_emotion:Joy>Hooray!</more_emotion:Joy>
</more_emotion:Emotion>

在伪代码中考虑它我需要类似的东西

for each element or attribute in document
    if element or attribute exists in destination schema
        copy element or attribute to destination document
    else
        discard element or attribute

我不知道该怎么做(或者在 XSLT 中是否可以)的部分是 if element or attribute exists in destination schema

【问题讨论】:

  • 请注意:我意识到我可以简单地编写只复制Joy 元素的XSLT。或者,我可以使用 XSLT 来复制除 AngerConfusion 之外的所有内容。但是,我不是在问如何做到这一点。我的真实情况要复杂得多,我在这里将其简化为我能想到的最简单的情况。
  • 有像 Altova 的 MapForce 这样的工具可以进行 XSD 到 XSD 的映射,但即便如此,您也需要提供一些手动干预,如果它不仅仅是微不足道的,它可能不会 100%映射。此外,您的输出 XML 的命名空间并未映射输出 XSD 的所需命名空间,因此您可能也想检查一下。
  • 是的,命名空间不同。我的 XSLT 也需要考虑这一点,但这是我已经解决的另一个问题。两种模式中有 95% 是相同的(名称空间更改除外);我正在尝试为另外 5% 制定计划。

标签: xml xslt xsd


【解决方案1】:

你想要这个有多复杂?您是否担心检查层次结构中元素的位置以查看其是否与架构中指定的内容相对应?还是真的只是检查元素名称是否存在于某处?

如果您确实想保持“简单”并检查在架构中的某处指定了元素名称,您可以首先使用 XSLT 身份转换开始

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

这会按原样复制所有节点和属性,因此您只需为要更改的内容编写模板。或者在您的情况下,对于您不想复制的内容。

使用“文档”功能,您可以创建一个模板,查找架构文档中没有任何同名的元素,然后忽略该元素。

<xsl:template match="*[not(local-name() = document('destination.xsd')//xs:element/@name)]" />

你可以为属性写一个类似的。试试这个 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xsl:output method="xml" indent="yes"/>

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

   <xsl:template match="*[not(local-name() = document('destination.xsd')//xs:element/@name)]" />

   <xsl:template match="@*[not(local-name() = document('destination.xsd')//xs:attribute/@name)]" />
</xsl:stylesheet>

这应该输出以下内容:

<more_emotion:Emotion xmlns:more_emotion="http://example.org/more_emotion">
   <more_emotion:Joy>Hooray!</more_emotion:Joy>
</more_emotion:Emotion>

请注意,如果您想继续处理“丢弃”元素的子元素,以查看它们是否匹配,请将第一个模板更改为此

<xsl:template match="*[not(local-name() = document('destination.xsd')//xs:element/@name)]">
   <xsl:apply-templates />
</xsl:template>

【讨论】:

  • 对于更复杂的映射(元素更改名称或在层次结构中移动),我相信我需要有特定的模板来处理这些场景。我认为这种简单的检查足以涵盖在源 xsd 中添加了在目标 xsd 中没有等效元素的其他场景。
  • 我能够对此进行测试,它的工作原理与您描述的完全一样。谢谢。
猜你喜欢
  • 2019-02-26
  • 2013-01-10
  • 2023-03-21
  • 2015-05-21
  • 2015-01-08
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 2023-03-23
相关资源
最近更新 更多