DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 創建一個 NIEM IEPD,第 3 部分: 擴展 NIEM
創建一個 NIEM IEPD,第 3 部分: 擴展 NIEM
編輯:XML詳解     

國家信息交換模型(National Information Exchange Model,NIEM)很大 — 6000 多個元素— 但是很可能不包含您想要包含在 XML 交換中的任何東西。本文不會介紹所有可能的場景,只介紹一些最常見的信息構建塊。在您創建的大多數信息交換包文檔(Information Exchange Package Documentation,IEPD)中,您將需要編寫一個擴展架構(extension schema),用於添加對交換是惟一的類型和屬性。對於如何以最大化 NIEM IEPD 之間互操作性的方式擴展該模型,NIEM 提供了詳細的指南。

  NIEM 模型也不為在交換中裝配所有對象而定義特定的消息類型或結構。而是由 IEPD 的創建者負責編寫一個交換架構(Exchange schema),來聲明消息的根元素和基本結構。

  在本系列的第 1 和第 2 部分中,我介紹了一個簡單的例子 Theft Report。圖 1 展示了我為交換創建的模型。我未能映射到基本 NIEM 模型的屬性和類型包括 Bicycle 和 TheftReport 類型,加上 IsRegistered、VehicleCategory 和 CountyCode 屬性。

  圖 1. 顯示有擴展的 IEPD 模型

    查看原圖(大圖)

  在本例中,NIEM 滿足我的大多數需求。但是我需要創建兩個新的架構:

  一個擴展架構,以定義 Bicycle 類型以及 IsRegistered、VehicleCategory 和 CountyCode 屬性。

  一個交換架構,以定義 TheftReport 類型(因為這是根元素),並提供一個結構以允許所有其他類型被包含在消息中。

  編寫 NIEM 架構

  NIEM 擴展架構和交換架構(以及生成的子集架構)都是用 XML Schema 編寫的。本文展示遵循 NIEM 的架構的一些例子,但是不詳細解釋 XML Schema 語言。如果您是架構方面的新手,我推薦您閱讀 XML Schema Primer,那裡有基本的介紹。

  除了 XML Schema 規定的約束之外,NIEM 還會增添它自己的規則,它的規則集中在 NIEM Naming and Design Rules (NDR) 文檔中。這些規則涉及很多方面,比如 NIEM 組件的命名和組織標准、允許和不允許的 XML Schema 構造種類,以及經核准的使用和擴展 NIEM 的方式。要遵循 NIEM,IEPD 中的架構必須遵循 NDR 規則。

  每個架構文檔必須具有其自己的目標名稱空間。對於我的示例 IEPD,我選擇使用 http://www.datypic.com/theftreport/extension/1.0(具有前綴 trext:)作為擴展架構的名稱空間,http://www.datypic.com/theftreport/Exchange/1.0(具有前綴 tr:)作為交換架構的名稱空間。

  使用反映名稱空間名稱的文件夾結構是一種慣例。在 Theft Report IEPD 中,我將創建名叫 extension 和 Exchange 的文件夾,並在每個文件夾中創建一個名叫 1.0 的子文件夾,我在其中放置各自的架構文檔。

  一個典型 NIEM 架構文檔的開頭部分 — 本例中是 Theft Report 例子的擴展架構 — 展示在 清單 1 中。

  清單 1. 一個遵循 NIEM 的架構的開頭部分

<xsd:schema targetNamespace="http://datypic.com/theftreport/extension/1.0" 
      version="1.0" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      XMLns:trext="http://datypic.com/theftreport/extension/1.0" 
      XMLns:s="http://niem.gov/nIEm/structures/2.0" 
      XMLns:nc="http://niem.gov/niem/nIEm-core/2.0" 
      XMLns:niem-xsd="http://niem.gov/nIEm/proxy/xsd/2.0" 
      XMLns:i="http://niem.gov/nIEm/appinfo/2.0"> 
 <xsd:annotation> 
  <xsd:documentation>Theft Report extension schema</xsd:documentation> 
  <xsd:appinfo> 
   <i:ConformantIndicator>true</i:ConformantIndicator> 
  </xsd:appinfo> 
 </xsd:annotation> 
 <xsd:import schemaLocation="../../niem/nIEm-core/2.0" 
       namespace="http://niem.gov/niem/nIEm-core/2.0"/> 
 <xsd:import schemaLocation="../../nIEm/proxy/xsd/2.0/xsd.xsd" 
       namespace="http://niem.gov/nIEm/proxy/xsd/2.0"/> 
 <xsd:import schemaLocation="../../nIEm/structures/2.0/structures.xsd" 
       namespace="http://niem.gov/nIEm/structures/2.0"/> 
 <xsd:import schemaLocation="../../nIEm/appinfo/2.0/appinfo.xsd" 
       namespace="http://niem.gov/nIEm/appinfo/2.0"/> 

  NIEM 架構文檔必須包含一個 xsd:annotation 元素(具有一個描述,在 xsd:documentation 中)和一個指示器(指出它是遵循 NIEM 的,在 xsd:appinfo 中)。

  跟任何架構一樣,它聲明並導入它需要直接引用的所有名稱空間。它也需要在 清單 1 的最後一行導入 appinfo 架構,用於聲明 xsd:appinfo 元素中使用的所有元素。

  注意:完整的擴展和交換架構文檔包含本文中的所有清單,可在 下載 處得到。

  擴展架構

  根據 IEPD 的復雜性,可能具有一個或很多個擴展架構。一些 IEPD 開發人員選擇將擴展架構按主題區域分解成多個文檔,以便在各種交換中更細粒度地重用架構。另外一些人選擇將可能比較頻繁變更版本的組件 — 例如代碼列表 — 放入單獨的架構文檔中。

  對於 Theft Report 例子,由於比較簡單,我選擇創建一個擴展架構。在 清單 1 中架構的開頭部分之後,我需要為我的自定義組件定義類型和聲明元素。有好幾種擴展 NIEM 的方式,我為我的每一種自定義使用不同的方法。

  使用置換組

  也許擴展 NIEM 最容易的方式是通過使用 置換組 來做到,置換組允許您聲明自己的元素和指定它是 NIEM 元素的替代。這意味著它可以出現在任何允許出現 NIEM 元素的地方。當 NIEM 模型中有一個語義上等價的元素,但是卻不太滿足需求時,可以使用該方法。例如,在我的模型中,我有一個 CountyCode 屬性,它在語義上等價於出現在地址中的 NIEM 抽象元素 nc:LocationCounty。在作為 NIEM 核心模型一部分的置換組中已經有兩個元素,但是它們不滿足我的需求:nc:LocationCountyCode 使用另外一個不同的代碼列表,nc:LocationCountyName 旨在用於清楚的名稱而不是代碼。相反,我聲明了一個新元素 trext:LocationCountyCode,它使用我自己的代碼列表。

  清單 2 展示了 trext:LocationCountyCode 的元素聲明。為了指出它是 nc:LocationCounty 的替代元素,我使用了一個 substitutionGroup 屬性。

  清單 2. trext:LocationCountyCode 元素以及一些相關類型的聲明

<xsd:element name="LocationCountyCode" type="trext:CountyCodeType" 
       substitutionGroup="nc:LocationCounty"> 
 <xsd:annotation> 
 <xsd:documentation>A county code.</xsd:documentation> 
 </xsd:annotation> 
</xsd:element> 
 
<xsd:simpleType name="CountyCodeSimpleType"> 
 <xsd:annotation> 
 <xsd:documentation>A data type for a county code.</xsd:documentation> 
 <xsd:appinfo> 
  <i:Base i:namespace="http://niem.gov/nIEm/structures/2.0" i:name="Object"/> 
 </xsd:appinfo> 
 </xsd:annotation> 
 <xsd:restriction base="xsd:token"> 
 <xsd:enumeration value="A"> 
  <xsd:annotation> 
   <xsd:documentation>Ascot County</xsd:documentation> 
  </xsd:annotation> 
 </xsd:enumeration> 
 <xsd:enumeration value="B"> 
  <xsd:annotation> 
   <xsd:documentation>Burke County</xsd:documentation> 
  </xsd:annotation> 
 </xsd:enumeration> 
 <xsd:enumeration value="C"> 
  <xsd:annotation> 
   <xsd:documentation>Cross County</xsd:documentation> 
  </xsd:annotation> 
 </xsd:enumeration> 
 </xsd:restriction> 
</xsd:simpleType> 
 
<xsd:complexType name="CountyCodeType"> 
 <xsd:annotation> 
 <xsd:documentation>A data type for a county code.</xsd:documentation> 
 <xsd:appinfo> 
  <i:Base i:namespace="http://niem.gov/nIEm/structures/2.0" i:name="Object"/> 
 </xsd:appinfo> 
 </xsd:annotation> 
 <xsd:simpleContent> 
 <xsd:extension base="trext:CountyCodeSimpleType"> 
  <xsd:attributeGroup ref="s:SimpleObjectAttributeGroup"/> 
 </xsd:extension> 
 </xsd:simpleContent> 
</xsd:complexType> 

  清單 2 也展示了兩個支持 trext:LocationCountyCode 元素的類型定義。首先,定義了一個簡單的類型,它為每個代碼值具有 xsd:enumeration 元素。然後,基於該簡單類型定義了一個復雜類型。通過對 s:SimpleObjectAttributeGroup 的引用,復雜類型添加了所有 NIEM 對象上都允許的通用屬性,比如 s:id。

  創建全新的類型

  NIEM 擴展的另一種方法是創建一個全新的類型。在我的模型中,Bicycle 在 NIEM 模型中根本就沒有等價元素,所以我需要創建一個新元素和一個相應的新復雜類型。每次添加一個新類型時,都應該考慮它是不是現有 NIEM 類型 — 例如,nc:ActivityType、nc:PersonType 或 nc:ItemType — 的專門化。對於 Bicycle,我決定它應該基於 nc:ConveyanceType,因為後者代表一種交通方式,適合於自行車(bicycle)。同樣,nc:ConveyanceType 已經具有我需要的大多數屬性,比如序列號和描述。

  跟前一種擴展方法一樣,我必須定義一個新元素(trext:Bicycle)和一個類型(trext:BicycleType)。清單 3 展示了這些定義。

  清單 3. trext:Bicycle 元素和相關類型的聲明

<xsd:element name="Bicycle" type="trext:BicycleType"> 
 <xsd:annotation> 
 <xsd:documentation>A bicycle.</xsd:documentation> 
 </xsd:annotation> 
</xsd:element> 
 
<xsd:complexType name="BicycleType"> 
 <xsd:annotation> 
 <xsd:documentation>A data type for a bicycle.</xsd:documentation> 
 </xsd:annotation> 
 <xsd:complexContent> 
 <xsd:extension base="nc:ConveyanceType"> 
  <xsd:sequence> 
   <xsd:element ref="trext:BicycleRegisteredIndicator" minOccurs="0" maxOccurs="1"/> 
  </xsd:sequence> 
 </xsd:extension> 
 </xsd:complexContent> 
</xsd:complexType> 

  trext:BicycleType 的類型定義表明,它擴展了 nc:ConveyanceType。注意,如果創建一個真正的新類型 — 就是說,不基於 NIEM 中任何已有的概念 — 那麼必須將您的類型基於 s:ComplexObjectType,這是 NIEM 中所有復雜類型的根。

  在 trext:BicycleType 中,我引用了一個 trext:BicycleRegisteredIndicator 元素,這是我必須單獨聲明的元素。NIEM 架構中的所有元素、屬性和類型都是全局的、惟一命名的頂層組件。清單 4 展示了 trext:BicycleRegisteredIndicator 元素的聲明。

  清單 4. trext:BicycleRegisteredIndicator 元素的聲明

<xsd:element name="BicycleRegisteredIndicator" type="nIEm-xsd:boolean"> 
 <xsd:annotation> 
 <xsd:documentation>Whether a bicycle is registered.</xsd:documentation> 
 </xsd:annotation> 
</xsd:element> 

  跟 trext:LocationCountyCode 具有自己的代碼列表類型不同,trext:BicycleRegisteredIndicator 具有一個對應於 XML Schema 內置類型 boolean 的類型。但是,我不是給它指定內置類型 xsd:boolean,而是使用 niem-xsd:boolean。定義在 “代理” 架構 xsd.xsd 中的這個復雜類型指定,該元素包含一個 xsd:boolean 值,但是也允許通用 NIEM 屬性,比如 s:id。

  向現有類型添加屬性

  另一個擴展情形是,您具有一個語義上等價於 NIEM 類型的復雜類型,但是需要在某些方面做修改或者添加內容。在我的模型中,MotorVehicle 類等價於 NIEM nc:VehicleType,但是需要一個額外的屬性 VehicleCategoryCode。在進行映射時,我考慮用 nc:ItemCategoryText 作為可能的映射候選者,但是覺得它太一般了。事實上,VehicleCategoryCode 屬性代表一個針對稅務的交通工具分類,所以我決定將該元素叫做 trext:VehicleTaxClassCode。

  所需的 XML Schema 定義類似於 Bicycle 擴展。清單 5 展示了我如何聲明一個新元素(trext:Vehicle)和一個新的復雜類型(即 trext:VehicleType,擴展了 nc:VehicleType)。

  清單 5. trext:Vehicle 元素和相關類型的聲明

<xsd:element name="Vehicle" type="trext:VehicleType"> 
 <xsd:annotation> 
 <xsd:documentation>A motor vehicle.</xsd:documentation> 
 </xsd:annotation> 
</xsd:element> 
 
<xsd:complexType name="VehicleType"> 
 <xsd:annotation> 
 <xsd:documentation>A data type for a motor vehicle.</xsd:documentation> 
 </xsd:annotation> 
 <xsd:complexContent> 
 <xsd:extension base="nc:VehicleType"> 
  <xsd:sequence> 
   <xsd:element ref="trext:VehicleTaxClassCode" minOccurs="0" maxOccurs="1"/> 
  </xsd:sequence> 
 </xsd:extension> 
 </xsd:complexContent> 
</xsd:complexType> 

  利用現有類型添加新對象

  有時,您會對 NIEM 類型很滿意,但是想要使用更加特定於您的交換的名稱。在我的模型中,我決定 Theft 類對應於 NIEM nc:ActivityType。但是將我的元素叫做 nc:Activity,我不是完全滿意,因為這個名稱太一般了,不夠具有描述性。在本例中,我選擇聲明一個新元素,命名為 trext:Theft,但是使用現有類型 nc:ActivityType,而不是定義一個新類型。清單 6 展示了該元素聲明。

  清單 6. trext:Theft 元素的聲明

<xsd:element name="Theft" type="nc:ActivityType"> 
 <xsd:annotation> 
 <xsd:documentation>A theft incident.</xsd:documentation> 
 </xsd:annotation> 
</xsd:element> 

  交換架構

  交換架構包含獨特於某個消息類型或消息類型組的定義。這一般只包含根元素和它的類型以及一些可能的結構元素(它們形成消息的基本框架)。通常,交換架構是 IEPD 特定的,而擴展架構可能跨幾個 IEPD 共享。

  您不需要具有單獨的交換架構和擴展架構;可以將您的所有擴展放在同一個架構文檔中。您也可以具有多個交換架構,以代表不同的消息類型或不同消息類型組。

  交換架構遵循前面描述的針對擴展架構的所有規則。例如,它們必須具有自己的目標名稱空間,並且必須具有注解。

  在 Theft Report 例子中,交換架構將包含 tr:TheftReport 元素(因為它是根元素)及其類型。它將包含一個 TheftReportDate,這顯示在模型中。但是更為重要的是,tr:TheftReport 將聚攏交換中定義的所有對象和相關元素。TheftReport 的元素和類型展示在 清單 7 中。

  清單 7. tr:TheftReport 元素和相關類型的聲明

<xsd:element name="TheftReport" type="tr:TheftReportType"> 
 <xsd:annotation> 
 <xsd:documentation>A theft report.</xsd:documentation> 
 </xsd:annotation> 
</xsd:element> 
 
<xsd:complexType name="TheftReportType"> 
 <xsd:annotation> 
 <xsd:documentation>A data type for a theft report.</xsd:documentation> 
 <xsd:appinfo> 
  <i:Base i:namespace="http://niem.gov/nIEm/structures/2.0" i:name="Object"/> 
 </xsd:appinfo> 
 </xsd:annotation> 
 <xsd:complexContent> 
 <xsd:extension base="s:ComplexObjectType"> 
  <xsd:sequence> 
   <xsd:element ref="tr:TheftReportDate" minOccurs="1" maxOccurs="1"/> 
   <xsd:element ref="trext:Theft" minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="nc:ActivityConveyanceAssociation" 
                  minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="trext:Vehicle" minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="trext:Bicycle" minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="j:ActivityLocationAssociation" 
                  minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="nc:Location" minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="j:ActivityVictimAssociation" 
                  minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="j:Victim" minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="j:ActivityWitnessAssociation" 
                  minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="j:Witness" minOccurs="0" maxOccurs="unbounded"/> 
   <xsd:element ref="nc:Person" minOccurs="0" maxOccurs="unbounded"/> 
  </xsd:sequence> 
 </xsd:extension> 
 </xsd:complexContent> 
</xsd:complexType> 

  注意,對象和關聯元素互為兄弟。這是一個典型的 NIEM 消息,其中對象之間的關聯是獨立的組件,它們通過 s:ref 屬性引用相關的對象。

  清單 8 中是一個消息片段,展示了一個賊(theft)與其位置(location)之間的關聯。對象 trext:Theft 和 nc:Location 是兄弟,它們各自具有一個 s:id 屬性,提供一個惟一的標識符。j:ActivityLocationAssociation 關聯是另一個兄弟,它使用帶有 s:ref 屬性的子元素將兩個對象鏈接在一起。

  清單 8. 顯示了關聯的樣例實例

<trext:Theft s:id="T1"> 
 <nc:ActivityDate> 
   <nc:DateTime>2006-05-04T08:15:00</nc:DateTime> 
 </nc:ActivityDate> 
</trext:Theft> 
 
<j:ActivityLocationAssociation> 
  <nc:ActivityReference s:ref="T1"/> 
  <nc:LocationReference s:ref="L1"/> 
</j:ActivityLocationAssociation> 
 
<nc:Location s:id="L1"> 
 <nc:LocationAddress> 
  <nc:StructuredAddress> 
   <nc:LocationStreet> 
    <nc:StreetFullText>123 Main Street</nc:StreetFullText> 
   </nc:LocationStreet> 
   <nc:LocationCityName>Big City</nc:LocationCityName> 
   <trext:LocationCountyCode>A</trext:LocationCountyCode> 
   <nc:LocationStateUSPostalServiceCode>MI</nc:LocationStateUSPostalServiceCode> 
   <nc:LocationPostalCode>49684</nc:LocationPostalCode> 
  </nc:StructuredAddress> 
 </nc:LocationAddress> 
</nc:Location> 

  表示對象之間關系的另一個選項是包含(containment),其中一個對象是另一個對象的父對象。例如,可以創建一個嶄新的 TheftType,其中包含一個人和一個位置或者一個對人或位置的引用。但是,這不是可取的使用 NIEM 的方法。將關聯與其他對象分開使得對象的描繪更為清晰,減少了遞歸式問題,而且更加適合於多到多關系。

  命名和組織 NIEM 組件

  您可能注意到例子中使用的名稱存在一些一致性。NIEM 對名稱施加某些規則:

  名稱具有一個對象術語(object term)和一個屬性術語(property term),如果它是一個簡單的元素,那麼還有一個表示術語(representation term)。例如,在名稱 BicycleRegisteredIndicator 中,Bicycle 是對象術語,Registered 是屬性術語,Indicator 是表示術語。還可以具有可選的限定術語(qualifIEr term)。

  有一組特定的經核准的表示術語,其中包括 Indicator、Code、Date、Text、Value 和 Quantity。

  所有名稱都使用駝峰式大小寫(即每個單詞的首字母大寫),而不使用分隔字符。

  屬性名以小寫字母打頭,而元素和類型名稱以大寫字母打頭。

  所有類型在名稱的末尾都有單詞 Type。

  也有控制 NIEM 組件組織的規則。所有架構、元素、屬性、類型和枚舉都必須具有定義,並且它們必須以一組經核准的開始短語(比如 A name of 或 A relationship)中的一個打頭。

  這只是規則的一個取樣;可以在 NDR 中找到 NIEM 規則的完整清單。

  修改子集

  在構建擴展架構和交換架構時,您可能需要自己的子集中不包括的來自 NIEM 的額外組件。例如,trext:BicycleRegisteredIndicator 的類型是 nIEm-xsd:boolean,這是一種不在我的初始子集中的類型。

  幸運的是,很容易使用架構子集生成工具(Schema Subset Generation Tool,SSGT)修改子集。從 SSGT 主頁,單擊右上角的 Options。這將打開 圖 2 中的頁面。

  圖 2. SSGT Options 頁面

    查看原圖(大圖)

  在 Load Wantlist 部分,填寫(或浏覽) wantlist.XML 文件名,然後單擊 Load Want List。這樣將在左邊窗格中打開您的子集。您然後可以單擊 Search,使用右邊窗格在您的 NIEM 子集中搜索和添加組件。完成後,重新生成子集。

  在構建擴展時,您有時想要使用 SSGT 來尋找類型而不是屬性。要找到 nIEm-xsd:boolean,我不能使用屬性上的默認搜索,因為這只找到元素和屬性名稱,找不到類型名稱。要專門尋找類型,請從 SSGT 的搜索頁面上的 Search for a 下拉菜單選擇 Types。

  在 CMT 中組織映射

  確保將您的擴展組織在本系列第 2 部分中描述的組件映射模板(Component Mapping Template,CMT)中。至少應該填寫您的擴展元素的 XPath 表達式。表 1 展示了我為 MotorVehicle 和 Bicycle 類填寫的擴展。

  表 1. 擴展的 XPath 映射

源類型 源屬性 ... 擴展? XPath MotorVehicle   ... Y trext:Vehicle MotorVehicle LicensePlate ... Y trext:Vehicle/ nc:ConveyanceRegistrationPlateIdentification/ nc:IdentificationID MotorVehicle VehicleCategory ... Y trext:Vehicle/ trext:VehicleTaxClassCode Bicycle   ... Y trext:Bicycle Bicycle IsRegistered ... Y trext:Bicycle/ trext:BicycleRegisteredIndicator

  有些 NIEM 從業者創建更為正式的 CMT,即具有單獨的列指出擴展的種類、基本類型和元素以及語義排列的級別。對於我的 CMT,我選用一種更為寬松的定義依賴項的方法,即將此信息包含在 Comments 列中。最終的 Theft Report CMT 可從 下載 得到。

  結束語

  在本文中,我描述了擴展 NIEM 的過程。我解釋了擴展架構和交換架構的作用,並展示了基於 NIEM 組件添加新元素和類型的各種方法。現在創建 NIEM IEPD 的主要工作完成了。第 4 部分將描述最終的決定性步驟,即組裝 IEPD。我將逐個介紹組成 IEPD 的各個工件。結果是一個完全的、遵循 NIEM 的 Theft Report IEPD。

下載

描述 名字 大小 下載方法 組件映射模板(CMT) nIEm3mapping.zip 26KB HTTP NIEM 交換、擴展和子集架構 nIEm3schemas.zip 17KB HTTP


XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved