【问题标题】:Convert DTD to XSD with defined root (starting) element使用定义的根(起始)元素将 DTD 转换为 XSD
【发布时间】:2012-05-28 17:20:10
【问题描述】:

我有几个大的 DTD 文件。我已经使用trang 将它们转换为 XSD 文件,因此我可以轻松地从 JAXB 和其他实用程序中使用它。但是,生成的 XSD 文件在顶层具有所有声明的元素。这意味着任何元素都可以是输入 XML 的根元素。我只想指定一个特定的元素。

拥有这些多个根元素会导致一些问题,例如xjc 为所有类生成@XmlRootElement,所以我需要添加更多额外的检查。

据我了解,我需要重写生成的 XSD,将 <xs:element>s 移动到 <xs:complexType>s,将 element refs 更改为 element types 等等,但这将是太多的猴子工作,与无法验证是否所有操作都正确。

有没有更有效的方法来做到这一点?

【问题讨论】:

  • +1 表示一个有意义的问题,但我们还要明确一点,DTD 到 XSD 的转换始终只是近似值。
  • @JirkaHanika 据我了解,生成的 XSD 非常接近 DTD。除了 DOCTYPE 定义(不过并不奇怪)和一些命名空间的东西。此外,一些奇怪的 DTD 结构也无法巧妙地转换为 XSD。我目前面临的唯一问题是 DTD 没有定义根元素的概念。 (RelaxNG 确实用<start> 定义了它,但它的支持很差,xjc 失败了)。
  • 是的,但是命名空间的东西是个大问题。此外,许多命名相似的结构意味着完全不同的东西。对第一个答案 +1,因为它不假装任何 XSD 语义。
  • 正确定义文档非常重要,无论是哪种灵长类动物,我认为都应该手工完成。唯一比不得不做更糟糕的是做错了。

标签: java xml xsd jaxb dtd


【解决方案1】:

根据您所描述的内容,并且忽略某些 cmets 中指出的转换的“保真度”,我只是在处理这样一个事实,即您只是在寻找某种自动方式(我称之为) XML 架构重构。我与 QTAssistant 相关联,这是一款专门用于此类工作的产品,所以我会这样做......

无论如何,您必须手动完成的一件事是找出并捕获您希望以 root 身份(或不以)身份查看的元素列表...然后您就完成了:点击一个按钮,或者调用命令行,您就可以确定是否生成了有效的 XSD。

重构引擎采用访问者模式,在您的情况下,它基本上可以满足您的需求:在需要时创建全局类型,删除不需要的全局元素定义,并使用内联声明替换任何引用的元素。

(对于阅读本文并了解替换组的任何人,此重构不会替换对替换组负责人的引用;因为我们讨论的是来自 DTD 的 XSD,所以这不是问题)。

这种简单性以及可重复且可靠的事实将是使用专用重构工具的主要优势;另一个优点:它还可以重新分配 xml 命名空间,无论如何你想要......

如果您对更多细节感兴趣,请告诉我,我会用一个小样本和一些插图更新这篇文章。

【讨论】:

    【解决方案2】:

    我使用简单的 XSLT 转换来处理生成的 XSD。适合我的情况:

    <?xml version="1.0"?>
    
    <xsl:stylesheet version="1.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:xs="http://www.w3.org/2001/XMLSchema"
            >
        <xsl:template match="@*|node()|comment()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()|comment()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="xs:element/@ref"/>
        <xsl:template match="xs:element[@ref]">
            <xsl:copy>
                <xsl:apply-templates select="@*"/>
                <xsl:attribute name="type"><xsl:value-of select="@ref"/></xsl:attribute>
                <xsl:attribute name="name"><xsl:value-of select="@ref"/></xsl:attribute>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="xs:element[@name = //xs:element/@ref and xs:complexType]">
            <xs:complexType name="{@name}">
                <xsl:apply-templates select="xs:complexType/node()"/>
            </xs:complexType>
        </xsl:template>
        <xsl:template match="xs:element[@name = //xs:element/@ref and @type]">
            <xsl:choose>
                <xsl:when test="//xs:complexType[@name = current()/@type]">
                    <xs:complexType name="{@name}">
                        <xs:complexContent>
                            <xs:extension base="{@type}"/>
                        </xs:complexContent>
                    </xs:complexType>
                </xsl:when>
                <xsl:otherwise>
                    <xs:simpleType name="{@name}">
                        <xs:restriction base="{@type}"/>
                    </xs:simpleType>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    </xsl:stylesheet>
    

    它检测引用的元素定义并将它们设为comptexTypes,更改引用。所有未引用的元素都成为起始元素。

    【讨论】:

      猜你喜欢
      • 2012-02-26
      • 2021-08-27
      • 2012-07-13
      • 2011-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      相关资源
      最近更新 更多