2011-04-19 75 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