级别: 初级 Shane Curcuru (shane_curcuru@us.ibm.com), 顾问软件工程师, IBM
2002 年 6 月 07 日 更新 2002 年 8 月 16 日 随着模式使用的发展,对于操作模式的工具需求也在增加。新的模式信息集模型(Schema Infoset Model)提供了模式本身的完整建模,包括一个模式或一组模式内的具体表示法和抽象关系。本文将显示该库方便地查询模式模型获取有关其详细信息的一些能力;我们还可以更新该模式以修正发现的任何问题并写回该模式。
注:本技巧文章假设您已经基本了解模式文档;
参考资料中有许多至模式文档和教程的链接.
虽然有许多使用模式来验证或分析 XML 文档的解析器和工具,
但允许对模式文档本身进行查询和高级操作的工具仍处于构建中。模式信息集模型(也称为 IBM 模式组件 Java 库,或者就是“库”)
提供了一个丰富的 API 库来对模式进行建模,包括模式的具体表示法(或许在 schema.xsd 文件中)和如同规范所定义的模式中的抽象概念。正如读过该模式规范的任何人都知道的,它们十分详细,而且该模型努力揭示任何模式内的所有详细信息。
于是,这将允许您有效地管理模式集合,并授予更高级别的模式工具 ― 或许是支持模式的解析器和转换程序。
模式信息集模型 UML 图
该库包括实际库类的各种 UML 图,它提供了对公共模式组件的关系和属性的快速概述。
抽象模式组件关系
本图显示了模式信息集组件之间的关系 ―
如在该库中那样建模的模式对象之间的抽象关系。黑色菱形表示强组合或聚合;空菱形表示弱聚合。
抽象模式组件属性
本图显示了如在该库中那样建模的抽象模式组件的一些属性,以及一部分类层次结构。
这些图都包括在该库的文档中,其中包括抽象和具体类树的几个其它 UML 图。
|
有关显示所有已建模的模式对象的库接口清单,请参阅
模式信息集模型 UML 图。
该库还包括在构建库接口本身时使用的 UML 图;这些图显示了库对象之间的关系,它们十分接近地模拟了模式规范中的概念。
在该示例中,您需要检查您的模式是否可能无法对整数派生的类型指定限制。
这可能有助于确保限制采购订单中的所有订购数量。这里,模式必须非常明确,所以您必需要求从整数派生出来的所有简单类型都包括 min/maxInclusive 或 min/maxExclusive facet。不过,如果 min/maxInclusive 或 min/maxExclusive facet 继承派生了该类型的类型,那么那仍是足够的。
虽然可以使用 XSLT 或 XPath 来查询
.xsd 文件中或一些其它
.xml 内容中模式的具体表示,但要发现模式组件实际拥有的类型派生和相互关系就困难得多了。
因为模式信息集模型库对模式的具体表示和抽象概念进行建模,所以可以方便地使用它来收集有关其组件的详细信息,
即使当模式可能有深类型层次结构或在多个模式文件中定义时,也可以这样做。
在这个简单模式中,您将发现有些类型满足具有 max/min facet 的标准,而有些类型不满足具有 max/min facet 的标准。(可以在
zip 文件中包括的
FindTypesMissingFacets.xsd 中找到完整模式。)
清单 1. 样本模式
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.research.ibm.com/XML/NS/xsd"
xmlns="http://www.research.ibm.com/XML/NS/xsd">
<!-- SimpleType missing both max/min facets -->
<xsd:simpleType name="integer-noFacets">
<xsd:restriction base="xsd:integer"/>
</xsd:simpleType>
<!-- Derived type has inherited min facet but missing max facet -->
<xsd:simpleType name="positiveInteger-inheritedMinFacet">
<xsd:restriction base="xsd:positiveInteger"/>
</xsd:simpleType>
<!-- Derived type with both effective max/min facets -->
<xsd:simpleType name="positiveInteger-bothFacets">
<xsd:restriction base="positiveInteger-inheritedMinFacet">
<xsd:maxExclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
<!-- etc... -->
</xsd:schema>
|
库可以读写多种源中的模式对象。我将通过使用 IBM WebSphere EMF ResourceSet 框架方便地地装入模式集来显示它;
您也可以直接从自己管理的 DOM 对象构建并发出模式,或者直接将模式构建并发到您自己管理的 DOM 对象。
该库提供了一种定制的
XSDResourceSet 实现,通过包含、导入和重定义,该实现可以智能且自动地装入相关的模式集。
在该库中还对相关模式之间的抽象关系进行建模。
清单 2. 装入模式
// String variable schemaURL is "FindTypesMissingFacets.xsd" or the URL to your schema
// Create a resource set and load the main schema file into it.
ResourceSet resourceSet = new ResourceSetImpl();
XSDResourceImpl xsdSchemaResource = (XSDResourceImpl)resourceSet.load(schemaURL);
// getResources() returns an iterator over all the resources, therefore, the main resource
// and those that have been included, imported, or redefined.
for (Iterator resources = resourceSet.getResources().iterator();
resources.hasNext(); /* no-op */)
{
// Return the first schema object found, which is the main schema
// loaded from the provided schemaURL
Resource resource = (Resource)resources.next();
if (resource instanceof XSDResourceImpl)
{
XSDResourceImpl xsdResource = (XSDResourceImpl)resource;
// This returns a com.ibm.etools.xsd.XSDSchema object
return xsdResource.getSchema();
}
}
|
既然您有了一个
XSDSchema 对象,就需要查询它以找到缺少 max/min facet 的任何类型。
首先,您将使用一些便利的库方法来快速找到从内置整数类型派生的所有
simpleTypeDefinition 。
由于该库为模式的抽象意义提供了一个完整模型,所以最后证明它非常直接。
您可以查询
XSDSchema ,以获得它的
getTypeDefinitions() 清单,
然后过滤出实际从基整数类型继承的
XSDSimpleTypeDefinition 。
清单 3. 获取特定类型列表
// A handy convenience method quickly gets all
// typeDefinitions within the schema
List allTypes = schema.getTypeDefinitions();
ArrayList allIntegerTypes = new ArrayList();
for (Iterator iter = allTypes.iterator();
iter.hasNext(); /* no-op */)
{
XSDTypeDefinition typedef = (XSDTypeDefinition)iter.next();
// Filter out for only simpleTypes...
if ((typedef instanceof XSDSimpleTypeDefinition)
// ... and filter for built-in integer types
// Use a worker method in the very handy sample
// program com.ibm.etools.xsd.util. XSDSchemaQueryTools
&& XSDSchemaQueryTools.isTypeDerivedFrom(typedef,
schema.getSchemaForSchemaNamespace(), "integer"))
{
// The filter found one; save it and continue.
allIntegerTypes.add(typedef);
}
}
|
W3C 模式规范中定义的每个组件都在库中进行了详细的建模。
既然您有了一个从整数派生的所有
XSDSimpleTypeDefinition 的列表,
就可以查询该列表,以获得缺少其 max 或 min facet 的
XSDSimpleTypeDefinition ,并产生一个报告。
注:库可以方便地将有效的 max/minExclusive 或 max/minInclusive facet 分组在一起,以便快速搜索;
它还提供了对每个类型的详细访问,如果需要,其中包括对实际的词法值的访问。
清单 4. 查询 XSDSimpleType 组件
for (Iterator iter = allIntegerTypes.iterator();
iter.hasNext(); /* no-op */)
{
XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition)iter.next();
// First, exclude any UNION or LIST types, since
// the schema spec says they can't have min/max facets:
// Part 2: Datatypes in:
//
'4.1.5 Constraints on Simple Type Definition Schema Components'
if ((XSDVariety.LIST == simpleType.getValueVariety())
|| (XSDVariety.UNION == simpleType.getValueVariety()))
{
// Unions and lists cannot have min/max facets at all,
// so there's no need to report them
continue;
}
// Get the effective max/min facets for each type -
// this includes ones declared in this type or
// ones that are inherited, and so forth
XSDMaxFacet maxFacet = simpleType.getEffectiveMaxFacet();
XSDMinFacet minFacet = simpleType.getEffectiveMinFacet();
// If you don't have the proper ones, report the error.
if ((null == maxFacet) || (null == minFacet))
{
if (simpleType.isSetName())
{
// A component's URI in the library is effectively
// its <target namespace>#<name>
System.out.println("Schema named component: " + simpleType.getURI() );
}
else
{
// It's an anonymous type, so ask the library
// to construct a default 'alias' for it
System.out.println("Schema anonymous component: " + simpleType.getAliasURI() );
}
System.out.print(" is missing these required facets: ");
if (null == maxFacet)
{
System.out.print(" XSDMaxFacet (either inclusive or exclusive) ");
}
if (null == minFacet)
{
System.out.print(" XSDMinFacet (either inclusive or exclusive) ");
}
// You could also report on the facets this type does have like:
// if (minFacet.isExclusive) {
// System.out.println("minFacet.getValue=" + minFacet.getValue());
// }
}
}
|
仅通过少量代码,我们就已经发现有关该模式的一些相当详细的信息。如果下载样本代码并相对于所提供的模式文件来运行这个样本代码,
那么您应该看到一个与下面相似的清单:
清单 5. 输出报告
Schema missing max/min facet report on: FindTypesMissingFacets.xsd
Schema named component: http://www.research.ibm.com/XML/NS/xsd#integer-minFacet
is missing these required facets: XSDMaxFacet (either inclusive or exclusive)
Schema named component: http://www.research.ibm.com/XML/NS/xsd#integer-noFacets
is missing these required facets: XSDMaxFacet (either inclusive or exclusive)
XSDMinFacet (either inclusive or exclusive)
Schema named component: http://www.research.ibm.com/XML/NS/xsd#positiveInteger-inheritedMinFacet
is missing these required facets: XSDMaxFacet (either inclusive or exclusive)
|
虽然这是一个预先设计的示例,但它的确显示了库中模式的详细表示如何使正确查找您所需的模式部分变得容易。
库为模式组件的特性提供了写方法,所以很容易通过添加任何缺少的 facet 来更新样本,以自动修正任何发现的类型。
而且因为库还对模式的具体表示进行建模,所以您可以将更新的模式写回
.xsd 文件。
样本程序
XSDFindTypesMissingFacets.java 显示了本文中的示例。
它使用模式文档
FindTypesMissingFacets.xsd ,该文档有许多带 max/min facet 的类型和不带 max/min facet 的类型。
可以在
zip 文件中下载该样本程序和下列样本 .java 文件。
同时还随附了通常与模式信息集模型一起提供的几个其它样本 .java 文件的副本。这些副本包括:
-
XSDSchemaQueryTools.java 展示了许多种对模式对象执行高级查询的其它方法。
-
带有便利方法的
XSDSchemaBuildingTools.java ,用于通过编程构建模式。
-
XSDPrototypicalSchema.java 使用该库来构建一直流行的模式
初级 PurchaseOrder 样本。
关于作者  | |  | Shane Curcuru 是有 12 年工作经验的 Lotus 和 IBM
开发人员和质量工程师,他是 Apache Software Foundation
的成员。他曾经工作于多个项目,如 Lotus 1-2-3、 Lotus eSuite、
Apache Xalan-J XSLT 处理器以及一些 XML Schema 工具。您可以通过
shane_curcuru@us.ibm.com
与 Shane Curcuru 联系。
|
对本文的评价
|