您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
创建一个 NIEM IEPD,第 3 部分: 扩展 NIEM
 
  1842  次浏览      19
 2018-8-3
 
编辑推荐:
本文来自于ibm.com,描述了扩展 NIEM 的过程,解释了扩展架构和交换架构的作用,基于 NIEM 组件添加新元素和类型的各种方法。

国家信息交换模型(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 的文本版本。)

图 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 : Conformant Indicator >
</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 : documen tation >
</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: documenta tion >
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value = "B">
<xsd:annotation>
<xsd:documentation> Burke County </xsd : documenta tion >
</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: Simple Object AttributeGroup "/>
</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: BicycleRegistered Indicator " 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 : Vehicle Type ">
<xsd:annotation>
<xsd:documentation>A motor vehicle .</xsd : documen tation >
</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: Activity Type ">
<xsd: annotation>
<xsd: documentation>A theft incident .</xsd : do cumentation>
</xsd: annotation>
</xsd :element>

交换架构

交换架构包含独特于某个消息类型或消息类型组的定义。这一般只包含根元素和它的类型以及一些可能的结构元素(它们形成消息的基本框架)。通常,交换架构是 IEPD 特定的,而扩展架构可能跨几个 IEPD 共享。

您不需要具有单独的交换架构和扩展架构;可以将您的所有扩展放在同一个架构文档中。您也可以具有多个交换架构,以代表不同的消息类型或不同消息类型组。

交换架构遵循前面描述的针对扩展架构的所有规则。例如,它们必须具有自己的目标名称空间,并且必须具有注解。

在 Theft Report 例子中,交换架构将包含 tr:TheftReport 元素(因为它是根元素)及其类型。它将包含一个 TheftReportDate,这显示在模型中。但是更为重要的是,tr:TheftReport 将聚拢交换中定义的所有对象和相关元素。TheftReport 的元素和类型展示在 清单 7 中。

清单 7. tr:TheftReport 元素和相关类型的声明

<xsd: element name = "TheftReport" type = "tr : The ftReportType">
<xsd:annotation>
<xsd:documentation> A theft report. </xsd: documen tation >
</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: Activity Conveyance Associa tion"
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 :Street FullText >
</nc:LocationStreet>
<nc:LocationCityName> Big City </nc: Location CityName >
<trext:LocationCountyCode> A </trext :Location County Code>
<nc:LocationStateUSPostalServiceCode> MI </nc : Location StateUSPostal ServiceCode>
<nc:LocationPostalCode> 49684 </nc: Location PostalCode >
</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 的较大版本。)

图 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 映射

有些 NIEM 从业者创建更为正式的 CMT,即具有单独的列指出扩展的种类、基本类型和元素以及语义排列的级别。对于我的 CMT,我选用一种更为宽松的定义依赖项的方法,即将此信息包含在 Comments 列中。最终的 Theft Report CMT 可从 下载 得到。

结束语

在本文中,我描述了扩展 NIEM 的过程。我解释了扩展架构和交换架构的作用,并展示了基于 NIEM 组件添加新元素和类型的各种方法。现在创建 NIEM IEPD 的主要工作完成了。

   
1842 次浏览       19
 
相关文章

UML概览
UML图解:用例图(Use case diagram )
UML图解:活动图(activity diagram )
UML图解:类图(class diagram )
UML图解:对象图(object diagram)
UML图解:顺序图( sequence diagram )
 
相关文档

模型跟踪:跟踪图、矩阵、关系(建模工具EA)
自定义表格(Custom Table)在EA中的使用
元素的详情浏览控制
UAF 1.2规范解读(DMM 和 UAFML )
EA中支持的各种图表
EA中的界面原型建模
 
相关课程

UML与面向对象分析设计
UML + 嵌入式系统分析设计
业务建模与业务分析
基于SysML和EA进行系统设计与建模
基于模型的需求管理
业务建模 & 领域驱动设计