跳转到内容

XQuery/XQuery 和 XML Schema

来自 Wikibooks,开放世界中的开放书籍

在学习任何建模语言时,查看任何形式模型的示例实例都很有帮助。在开发 XML Schema 时,这一点同样适用。像 Oxygen 和 XML-Spy 这样的 XML 开发工具具有生成提供的 XML Schema 的随机实例的工具,但拥有一个 Web 服务来执行此操作也很有用。该服务也可用于测试数据生成。

以下是一个测试 XML Schema 文件

<xs:group name="TechnicalOrderVersionChoiceGroup">
  <xs:choice>
    <xs:element name="ettcsMigrationTov" type="ord:ETTCSMigrationTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsNewSiteBuildTov" type="ord:ETTCSNewSiteBuildTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsNewCabinetTov" type="ord:ETTCSNewCabinetTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsSimpleTov" type="ord:ETTCSSimpleTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="lteNewCabinetTov" type="ord:LTENewCabinetTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="gsmoeTov" type="ord:GSMoETechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsUpspeedTov" type="ord:ETTCSUpspeedTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsRehomeTov" type="ord:ETTCSRehomeTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsRebalanceTov" type="ord:ETTCSRebalanceTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="retTechnicalOrderVersion" type="ord:RETTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsNSBNGUNIEVCUplinkTechnicalOrderVersion" type="ord:ETTCSNSBNGUNIEVCUplinkTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsNSBNGUNIEVCAdditionalNode" type="ord:ETTCSNSBNGUNIEVCAdditionalNodeTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="eireTov" type="ord:EIRETechnicalOrderVersionType" minOccurs="0" />
    <!-- Granite Initiated Order Types -->
    <xs:element name="addEttcsMtsoCollectorCircuitTechnicalOrderVersion" type="ord:AddEttcsMtsoCollectorCircuitTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="r2BToR4BConversionTechnicalOrderVersion" type="ord:R2BToR4BConversionTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="eoSONETMtsoCollectorCircuitTechnicalOrderVersion" type="ord:EoSONETMtsoCollectorCircuitTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="disconnectEthernetEvcSegmentTechnicalOrderVersion" type="ord:DisconnectEthernetEvcSegmentTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcOc3MtsoR4DTechnicalOrderVersion" type="ord:EttcOc3MtsoR4DTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="gSMoEMtsoTechnicalOrderVersion" type="ord:GSMoEMtsoTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="disconnectLnsOewBaseSegmentTechnicalOrderVersionType" type="ord:DisconnectLnsOewBaseSegmentTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="disconnectLnsOewBaselinePathTechnicalOrderVersionType" type="ord:DisconnectLnsOewBaselinePathTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="discoEthernetSonetRehomeTov" type="ord:DiscoEthernetOverSonetForRehomeTechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="ethernetSonetRehomeMtsoTov" type="ord:EthernetOverSonetRehomeMtsoTechnicalOrderVersionType" minOccurs="0" />
    <!-- Iteration 17 - Two new Granite Initiated Order Types - for Aug2013 -->
    <xs:element name="gEttcsNSBNextGenUniEvcDualUplinkTov" type="ord:EttcsNSBNextGenUNIEVCDualUplinkTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="gEttcsNSBNextGenUniEvcMultiCabTov" type="ord:EttcsNSBNextGenUNIEVCMultiCabTechnicalOrderVersionType" minOccurs="0" />
    <!-- R12.1 INDOOR SMALL CELL EAMIS -->
    <xs:element name="smallCellEamis" type="ord:IndoorSmallCellEamisTechnicalOrderVersionType" minOccurs="0" />
    <!-- R13.1 Rapid Deployment-->
    <xs:element name="eoSonetOc12MtsoCollectorCircuitTov" type="ord:EoSonetOc12MtsoCollectorCircuitTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="indoorSmallCellBdslTov" type="ord:IndoorSmallCellBdslTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="indoorSmallCell3RdPartyTov" type="ord:IndoorSmallCell3RdPartyTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="indoorSmallCellSharedTransportTov" type="ord:IndoorSmallCellSharedTransportTechnicalOrderVersionType" minOccurs="0" />
    <!-- MLPPP WO Types -->
    <xs:element name="mlpppMigrationUMTS" type="ord:MLPPPMigrationUMTSTechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppMigrationDS1UMTS" type="ord:MLPPPMigrationDS1UMTSTechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppNewCabinetAddLTE" type="ord:MLPPPNewCabinetAddLTETechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppNewCabinetAddDS1LTE" type="ord:MLPPPNewCabinetAddDS1LTETechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppNewCabinetAddUMTS" type="ord:MLPPPNewCabinetAddUMTSTechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppNewCabinetAddDS1UMTS" type="ord:MLPPPNewCabinetAddDS1UMTSTechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppUpspeed" type="ord:MLPPPUpspeedTechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppUpspeedDS1" type="ord:MLPPPUpspeedDS1TechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppRehome" type="ord:MLPPPRehomeTechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppRehomeDS1" type="ord:MLPPPRehomeDS1TechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppRebalance" type="ord:MLPPPRebalanceTechnicalOrderVersionType" minOccurs="0" />    
    <xs:element name="mlpppRebalanceDS1" type="ord:MLPPPRebalanceDS1TechnicalOrderVersionType" minOccurs="0" />    
    <!-- ESCORE Initiated SmallCell WO Type - since R14.0 -->
    <xs:element name="smallcellTransport" type="ord:SmallCellTransportTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="smallcellSCR" type="ord:SmallCellSCRTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="smallcellSCS" type="ord:SmallCellSCSTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="smallcellAP" type="ord:SmallCellAPTechnicalOrderVersionType" minOccurs="0" /> <!-- Self install and Disconnect will use this same AP payload -->
    <!-- Since R1406 - Two new ETTCS automation IPv6 Types -->
    <xs:element name="ettcsIPv6Siad" type="ord:ETTCSIPv6MigrationSIADTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsIPv6ENodeB" type="ord:ETTCSIPv6MigrationENodeBTechnicalOrderVersionType" minOccurs="0" />
    <!-- Since R1404 - RD Types -->
    <xs:element name="ettcsUniversalEvcDownspeed" type="ord:EttcsUniversalEvcDownspeedTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="outdoorSmallCell3rdPartytTov" type="ord:OutdoorSmallCell3rdPartyTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="outdoorSmallCellBdslTov" type="ord:OutdoorSmallCellBdslTechnicalOrderVersionType" minOccurs="0" />
    <!-- Since R1406 - ETTCS Site Migration -->
    <xs:element name="ettcsSiteMigrBackhaul" type="ord:ETTCSSiteMigrationBackhaulTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="ettcsSiteMigrShorthaul" type="ord:ETTCSSiteMigrationShorthaulTechnicalOrderVersionType" minOccurs="0" />
    <!-- Since R1410 - IUB Trunking Support -->
    <xs:element name="iubTrunkingTov" type="ord:IUBTrunkingTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="infrastructureTov" type="ord:InfrastructureTechnicalOrderVersionType" minOccurs="0" />
    <xs:element name="EOMWTargetTov" type="ord:ETTCSNSBNGUplinkEoMWTargetTechnicalOrderVersionType" minOccurs="0" />
  </xs:choice>
</xs:group>

XQuery 将简单 XML Schema 转换为实例文档

[编辑 | 编辑源代码]

我们可以使用递归函数将此 XML Schema 转换为实例文档。这是一个此函数的实现,它涵盖了一些关键的 XML Schema 结构

declare namespace xs = "http://www.w3.org/2001/XMLSchema";
declare function local:process-element($element as node())  {
     typeswitch ($element)
        case  element(xs:complexType)   return 
              for $sub-element in  $element/*
                 return  local:process-element($sub-element)

        case element(xs:annotation) return
                ()
        case element(xs:element)   return
               let $min := ($element/@minOccurs,1)[1]
               let $max := 
                     if ($element/@maxOccurs = "unbounded") 
                     then 10
                     else ($element/@maxOccurs,1)[1]
               let $count := $min +  round(math:random() * ($max - $min))
               return 
                  if ($count  >0 )
                  then 
                      for $i in 1 to $count
                      return
                         if ($element/@ref)  
                         then 
                              local:process-element(root($element)/xs:schema/xs:element[@name=$element/@ref])
                         else 
                         if (root($element)/xs:schema/xs:complexType[@name=$element/@type]) 
                         then 
                             element {$element/@name} {                           
                                   local:process-element(root($element)/xs:schema/xs:complexType[@name=$element/@type])
                             }
                         else 
                         element {$element/@name} {                      
                             if  ($element/*)
                             then for $sub-element in $element/*
                                     return local:process-element($sub-element)
                             else  local:process-type(($element/@type,"xs:string")[1])  
                          
                      }
                    else ()
           case element(xs:attribute)   return
                 if ($element/@use="required"  or math:random() > 0.5)
                 then 
                     attribute {$element/@name} {
                         local:process-type($element/@type) 
                      }
                  else ()

           case  element(xs:sequence)   return
                 for $sub-element in $element/*
                       return local:process-element($sub-element)

           case  element(xs:all)   return
                 for $sub-element  in $element/*
                 order by math:random()
                 return local:process-element($sub-element)
                         
           case element(xs:choice)  return
                     let $count := count($element/*)
                    let $i := ceiling(math:random()*$count)
                    let $sub-element := $element/*[ $i]
                    return local:process-element($sub-element)
          default return
                   ()
};

此函数使用element结构基于 XML Schema 文件中的信息创建一个新的 XML 实例树,并使用typeswitch结构选择给定元素类型的适当处理。

类型实例生成

[编辑 | 编辑源代码]

需要一些辅助函数来生成(某些)标准类型的随机实例。


declare function local:pad($string as xs:string, $char as xs:string, $max as xs:integer) as xs:string {
   concat(string-pad($char,$max - string-length($string)), $string)
};

declare function local:pad2($string) {
   local:pad($string,"0",2)
};

declare function local:process-type($name )   {
(: just simple types - xs namespace :)
   if ($name = ("xs:string","xs:NMTOKEN","xs:NCName"))
   then  string-join(
              for $c  in  1 to  math:random() * 12
              return ("A","B","C","D")[ceiling(math:random() * 4)]
             , "")
   else if ($name="xs:integer")
   then  round(math:random()*100)
   else if ($name="xs:decimal")
   then math:random() * 100 - 50   
   else  if ($name="xs:boolean")
   then ("true","false")[ ceiling( math:random() *2)]
   else if ($name="xs:date")
   then string-join((1990 + round(math:random() * 20), 
                    local:pad2(ceiling(math:random()*12)) , 
                    local:pad2(ceiling(math:random()*30))),"-")
   else if ($name="xs:time")
   then string-join((local:pad2(floor(math:random() * 24)), 
                     local:pad2(floor(math:random()*60)) , 
                     local:pad2(floor(math:random()*60))),":")
   else if ($name="xs:dateTime")
   then concat (
          string-join((1990 + round(math:random() * 20), 
                       local:pad2(ceiling(math:random()*12)) , 
                       local:pad2(ceiling(math:random()*30))),"-"),
           "T",
           string-join((local:pad2(floor(math:random() * 24)),
                        local:pad2(floor(math:random()*60)) , 
                        local:pad2(floor(math:random()*60))),":")
           )
   else ()
};


这是一个基本脚本,它将此函数应用于示例模式。默认情况下,生成的实例的根是模式中的第一个元素,或者如果提供了根参数,则为命名元素。

let $file := request:get-parameter("file",())
let $root := request:get-parameter("root",())
let $schema :=  doc($file)
return 
  if ($root)
  then  local:process-element($schema/xs:schema/xs:element[@name=$root])  
  else  local:process-element($schema/xs:schema/xs:element[1])

执行

示例输出

[编辑 | 编辑源代码]
<Root>
    <Start>C</Start>
    <Any>
        <AnyA>BADADAD</AnyA>
        <AnyC>BA</AnyC>
        <AnyB>D</AnyB>
    </Any> 
    <Multiple>
        <Choice>
            <Third AttributeDecimal="8.937041402178778" AttributeTime="20:38:04" AttributeDateTime="1995-08-06T21:08:43"/>
        </Choice>
        <Unbounded>BDAACAAAA</Unbounded>
        <Ref>

            <Ref1>52</Ref1>
            <Ref2>1992-09-02</Ref2>
        </Ref>
        <WithRefType>
            <RefTypeA>BBBDD</RefTypeA>
            <RefTypeB>DAADCABDC</RefTypeB>
        </WithRefType>

    </Multiple>
    <Multiple>
        <Choice>
            <Second AttributeString="ADAB" AttributeDate="2005-12-16"/>
        </Choice>
        <Unbounded/>
        <Unbounded>CABBB</Unbounded>
        <Unbounded/>

        <Unbounded>B</Unbounded>
        <Unbounded>AACBABAABCB</Unbounded>
        <Ref>
            <Ref1>56</Ref1>
            <Ref2>1992-05-22</Ref2>
        </Ref>
        <WithRefType>

            <RefTypeA>CDAA</RefTypeA>
            <RefTypeB>CBDBDBDB</RefTypeB>
        </WithRefType>
        <Optional>CC</Optional>
    </Multiple>
    <Multiple>
        <Choice>

            <First AttributeInt="21" AttributeString="AABC" AttributeBoolean="true"/>
        </Choice>
        <Unbounded>ADADDDDDB</Unbounded>
        <Unbounded>DCDCBDDD</Unbounded>
        <Unbounded>CBAD</Unbounded>
        <Unbounded>DAAAD</Unbounded>
        <Ref>

            <Ref1>13</Ref1>
            <Ref2>1997-04-30</Ref2>
        </Ref>
        <WithRefType>
            <RefTypeA>CB</RefTypeA>
            <RefTypeB/>
        </WithRefType>

    </Multiple>
    <Multiple>
        <Choice>
            <Second AttributeString="DBDA" AttributeDate="1999-05-16"/>
        </Choice>
        <Unbounded>CCDDDDCD</Unbounded>
        <Unbounded>DDABACC</Unbounded>
        <Ref>

            <Ref1>44</Ref1>
            <Ref1>30</Ref1>
            <Ref1>57</Ref1>
            <Ref2>1997-01-26</Ref2>
        </Ref>
        <WithRefType>
            <RefTypeA>CBC</RefTypeA>

            <RefTypeB>CA</RefTypeB>
        </WithRefType>
    </Multiple>
    <End>95</End>
</Root>

待办事项

[编辑 | 编辑源代码]
  • 完整的一套 xml 类型
  • 混合
  • 限制(目前仅限枚举)
  • 属性组
  • complexType 中缺少属性的问题
  • 分发的提示
  • 命名空间
  • 随机化配置

参考文献

[编辑 | 编辑源代码]
华夏公益教科书