如何手动使用XSLT生成XSD

时间:2014-10-25 21:50:56

标签: xml xslt xsd dtd

我正在努力解决这个问题。我可以使用XSLT生成基于XML文件输入的XSD吗? 我知道我可以使用许多软件自动完成,但我需要通过编写代码来实现。

你能帮助我解决这个问题,并用有用的资源支持我吗?

这是一个示例XML文件:我需要使用XSLT生成XSD并验证它:

<test>
  <a>
    <b> </b>
  </a>
  <d> </d>
</test>

2 个答案:

答案 0 :(得分:3)

正如马库斯在评论中所说,有很多自由度,但这是一个开始:

您的输入XML:

<test>
  <a>
    <b> </b>
  </a>
  <d> </d>
</test>

鉴于此XSLT:

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

  <xsl:template match="/">
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xsl:apply-templates/>
    </xs:schema>
  </xsl:template>
  <xsl:template match="*[*]">
    <xs:element name="{local-name()}">
      <xs:complexType>
        <xs:sequence>
          <xsl:apply-templates select="*"/>
        </xs:sequence>
        <xsl:apply-templates select="@*"/>
      </xs:complexType>
    </xs:element>
  </xsl:template>
  <xsl:template match="*[not(*) and text()]">
    <xs:element name="{local-name()}">
      <xs:complexType>
        <xs:simpleContent>
          <xs:extension base="xs:string">
            <xsl:apply-templates select="@*"/>
          </xs:extension>
        </xs:simpleContent>
      </xs:complexType>
    </xs:element>
  </xsl:template>
  <xsl:template match="@*">
    <xs:attribute name="{local-name()}"/>
  </xsl:template>
</xsl:stylesheet>

产生此XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="test">
      <xs:complexType>
         <xs:sequence>
            <xs:element name="a">
               <xs:complexType>
                  <xs:sequence>
                     <xs:element name="b">
                        <xs:complexType>
                           <xs:simpleContent>
                              <xs:extension base="xs:string"/>
                           </xs:simpleContent>
                        </xs:complexType>
                     </xs:element>
                  </xs:sequence>
               </xs:complexType>
            </xs:element>
            <xs:element name="d">
               <xs:complexType>
                  <xs:simpleContent>
                     <xs:extension base="xs:string"/>
                  </xs:simpleContent>
               </xs:complexType>
            </xs:element>
         </xs:sequence>
      </xs:complexType>
   </xs:element>
</xs:schema>

加成

添加了属性的输入XML:

<test w="w1">
  <a x="x1" y="y1">
    <b z="z1"> </b>
  </a>
  <d> </d>
</test>

产生此XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="test">
      <xs:complexType>
         <xs:sequence>
            <xs:element name="a">
               <xs:complexType>
                  <xs:sequence>
                     <xs:element name="b">
                        <xs:complexType>
                           <xs:simpleContent>
                              <xs:extension base="xs:string">
                                 <xs:attribute name="z"/>
                              </xs:extension>
                           </xs:simpleContent>
                        </xs:complexType>
                     </xs:element>
                  </xs:sequence>
                  <xs:attribute name="x"/>
                  <xs:attribute name="y"/>
               </xs:complexType>
            </xs:element>
            <xs:element name="d">
               <xs:complexType>
                  <xs:simpleContent>
                     <xs:extension base="xs:string"/>
                  </xs:simpleContent>
               </xs:complexType>
            </xs:element>
         </xs:sequence>
         <xs:attribute name="w"/>
      </xs:complexType>
   </xs:element>
</xs:schema>

离开练习:

  • 生成除俄罗斯娃娃以外的XSD样式。
  • 处理名称空间。
  • 尽可能在字符串原语之外加强打字。
  • ...

答案 1 :(得分:2)

有许多模式描述任何给定的输入文档,因此找到一个生成您认为是“好”模式的算法是棘手的;它在很大程度上是一个试错过程,我知道这很有趣,因为我曾经自己做过。

在XSLT中执行它可能并不比在任何其他语言中执行它困难,尽管我自己的DTDGenerator是用Java编写的,因为它必须在流模式下工作(当时可能是15年前!)在XSLT中是不可能的。

重要的算法挑战是:给定元素E的子序列的N个实例,找到它们都符合的语法,而不会使语法如此微不足道,以至于毫无意义。例如,如果您有三个实例

<E><a/><b/><c/><d/></E>
<E><a/><a/><b/><c/></E>
<E><a/><a/><a/><b/><c/></d></d></E>

理想情况下,您想要提出内容模型a + b c d *。在我的DTD生成器中,我使用的算法是:首先消除重复,因此这些减少到abcd,abc和abcd。然后,如果其中一个是另一个的子串,则将其删除,因此您只剩下“abcd”。这形成了基本序列,然后您可以添加最小和最大基数。如果你有一个实例abcd和另一个abdc,那会更棘手;在这种情况下,我认为它可能表明顺序不重要,所以我生成了(a | b | c | d)*。但你可以尝试做得更好!

您还希望避免过度约束:仅因为元素的所有实例都是83到78392范围内的数字并不意味着您的模式应将这些数据强加为最小值和最大值。另一方面,如果它们都大于零,那么probbaly会告诉你一些事情。