2011-04-19 80 views
6

我需要基于XML文件创建XSD架构。有没有Perl模块可以做到这一点?如何从Perl中的示例XML文档创建模式?

+4

与此相关的问题:对于一个Java工具,见[庄](http://www.thaiopensource.com/relaxng/trang-manual.html#xsd-output)。相反的方向,请参阅[XML-Pastor](http://p3rl.org/XML::Pastor)。 – daxim 2011-04-20 10:21:10

+1

由XML文件生成的XSD文件没有太大价值。只能对XML文件的结构进行建模。 XSD文件将错过任何限制,因为您无法猜测2011年是一年,因此无法定义任何限制。仅建模结构的XSD文件是否会满足您的要求? – ceving 2011-05-04 09:17:47

回答

4

您可以使用任何XSLT处理器通过XSL转换来创建XSD。请参阅XML::XSLT

XSD文件包含两种元素类型:简单和复杂。所有的叶子节点必须被翻译成简单的类型元素,其他的必须被翻译成复杂的类型。叶节点是没有任何后代的节点。相应的XPath是//*[not(descendant::element())]。下面的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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="/"> 
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       elementFormDefault="qualified" 
       attributeFormDefault="unqualified"> 
     <xsl:for-each select="//*[not(descendant::element())]"> 
     <xsl:element name="xs:element"> 
      <xsl:attribute name="name"> 
      <xsl:value-of select="name()"/> 
      </xsl:attribute> 
      <xs:simpleType> 
      <xs:restriction base="xs:string"/> 
      </xs:simpleType> 
     </xsl:element> 
     </xsl:for-each> 
     <xsl:for-each select="//*[descendant::element()]"> 
     <xsl:element name="xs:element"> 
      <xsl:attribute name="name"> 
      <xsl:value-of select="name()"/> 
      </xsl:attribute> 
      <xs:complexType> 
      <xs:sequence> 
       <xsl:for-each select="child::*"> 
       <xsl:element name="xs:element"> 
        <xsl:attribute name="ref"> 
        <xsl:value-of select="name()"/> 
        </xsl:attribute> 
       </xsl:element> 
       </xsl:for-each> 
      </xs:sequence> 
      </xs:complexType> 
     </xsl:element> 
     </xsl:for-each> 
    </xs:schema> 
    </xsl:template> 
</xsl:stylesheet> 

下面的例子:

<?xml version="1.0" encoding="UTF-8"?> 
<person> 
    <firstname>Peter</firstname> 
    <lastname>Pan</lastname> 
    <born> 
    <year>1904</year> 
    <month>12</month> 
    <day>27</day> 
    </born> 
</person> 

将产生如下模式:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      elementFormDefault="qualified" 
      attributeFormDefault="unqualified"> 
    <xs:element name="firstname"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="lastname"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="year"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="month"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="day"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="person"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element ref="firstname"/> 
     <xs:element ref="lastname"/> 
     <xs:element ref="born"/> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
    <xs:element name="born"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element ref="year"/> 
     <xs:element ref="month"/> 
     <xs:element ref="day"/> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 
+1

适合我!由于您没有真正使用任何XSLT 2.0功能,因此您可以下载更广泛的1.0版本。你只需要将'descendant :: element()'改为'descendant :: *'。 – Lumi 2011-05-04 16:34:26

+0

另请参阅[XML :: LibXSLT](http://search.cpan.org/~pajas/XML-LibXSLT/),这是您在执行XSLT时在Perl中的最佳选择。 – Lumi 2011-05-04 16:36:04