`

<转>为 SOAP 更新 XML Schema

 
阅读更多

Shane Curcuru (shane_curcuru@us.ibm.com), 顾问软件工程师, IBM Research

2003 年 12 月 01 日

越来越多的项目使用 XML Schema 来定义它们的数据结构。随着您的 XML Schema 储存库越来越大,您需要一些工具来管理您的这些 XML Schema 。Eclipse XSD Schema Infoset Model 提供了强大的查询和编辑功能。在本文中, Shane Curcuru 将为我们演示如何更新一个与 SOAP 一起使用的 Schema,采用的方式是自动地将这些属性使用转变为元素声明。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

阅读本文要求您对 XML Schema 和 SOAP 机制有一定的了解。在 zip 文件中包含了一些样本代码,可以独立运行,也可以运行在 Eclipse 工作台中。

引言:一个更新 XML Schema 的示例

如果您构建了一个 Schema 的库,您也许会在新建的应用程序中重用它们。如果您已经建立了内部购买订单的数据模型,如果您想把它转变为 Web 服务,那么您需要更新这个 Schema ,使它能为 SOAP 所用。SOAP 允许您跨网络传递 XML 消息;XML 主体必须遵循 Schema 。然而, SOAP 通常是使用元素数据作为它自己的 XML 主体,而不是属性数据。这里,您可以看一段程序,它自动更新现有的 Schema 文档,将任何属性声明转换成基本“对等”的元素声明。


Changing attributes into elements



 



概述:如何进行

考虑到 XML Schema 的复杂性,您当然不乐意使用 Notepad 来编辑 .xsd 文件。一个良好的 XML 编辑器也无法一步到位,虽然它可以清楚的组织您的元素和属性,但是难以显示在 Schema 规范中定义的许多抽象 Infoset 关联。这也就是产生 Schema Infoset Model 的根源;它可以显示一个 Schema 文档集的具体 DOM 表示,也可以显示 Schema 的完全抽象 Infoset 模型。通过 Model 的编程 API以及 Model 内置的 Schema 样本编辑器,可以显示两者。

可视化 Schema 编辑

如果您将 XSD Schema Infoset Model 和 Eclipse Modeling Framework (EMF) 插件安装到您的 Eclipse 中,您可以在您的工作台中看到样本编辑器。 ( 注意:要浏览这个编辑器不需要遵循本文)。在 Navigator 中右键单击 schema.xsd 文件,然后选择 Open With... , 然后是 Sample XML Schema Editor 。您将看到一个标准 Eclipse 编辑器,显示了常见的 Source 视图 ——这就是您打开的 .xsd 文件的具体 DOM 表示。

在编辑器的底部,在 Source 视图后面有两个标签——Semantics 和 Syntax 。这两个树形视图显示了 Schema 组件之间的抽象 Infoset 关联。例如,在 Semantics 视图,您可以看到 Type 的顶层条目—— 这就是所有的 Schema 声明的类型(简单类型和复杂类型),还不仅仅局限于顶层条目,也不仅仅局限于该文档(例如,通过包含或者导入来打开 Schema 文档)。

在本例中,我将把这个问题稍微简化一下。 MakeSoapCompatible.java 是一个程序,试图从 Schema 中获取 attributeDeclarations ,然后转换成为基本对等的 elementDeclaration s ,并显示一些提示。

很显然,如果在 complexType 的 particle 中已经存在同名的元素,一开始您无法将属性转变成为元素。因此,首先检查命名冲突,然后拒绝更改这些属性。为了简化这个实例,任意声明一些条件,使得 Schema 和程序不匹配。我并不更改那些带通配符的 Schema ,因为需要进行复杂的命名检查,才能确保更改的属性不会和元素发生冲突。也不更新那些使用了 #all 或者 #choice 作为排序的组,因为这将以无法预期的方式更改组的含义。

 



 



评估 Schema 的不匹配

使用抽象 Infoset 关联的功能


首先,您需要查找 Schema 中的  complexType s ,因为只有这些地方才会真正地使用属性。您不需要搜索所有的属性声明,因为,之后您可以询问 complexType ,知道它真正使用的属性。查询您的 Schema 文档是一个非常简单的过程:遍历这些内容,查找复杂类型。注意:有多种查询方式可以用来验证 Schema 内容,在这里只是用了其中一种而已。

清单 1. 查找 complexType

// Find type definitions: for our purposes, the simplest 
//  way to get all complexTypes is to drop down to the 
//  underlying EMF model of a schema to iterate through 
//  all concrete components contained within this schema
List complexTypeDefinitions = new ArrayList();
for (Iterator iter = schema.eAllContents(); iter.hasNext(); )
{
    XSDConcreteComponent concreteComponent = (XSDConcreteComponent)iter.next();
    if (concreteComponent instanceof XSDComplexTypeDefinition)
    {
        complexTypeDefinitions.add(concreteComponent);
    }
}
// An alternate method would be to use the abstract Infoset 
//  relationship of schema.getTypeDefinitions(), which would 
//  get all globally-visible typedefs (simple and complex) 
//  within the whole schema, however that would miss any 
//  types that were nested inside of other components

 

现在,您已经得到了所有需要更新的 complexType s 列表,下面我们排除那些与样本程序不兼容的类型。因为您只是查询不同 Schema 组件的信息,您可以有效使用许多抽象 Infoset 关联,以及 Model 提供的方法。这些抽象方法自动考察这些基本类型和派生类型;对声明的引用;以及导入、包含和重定义 Schema 文档的结果。

清单 2. 查找不匹配的地方

// Detect name collisions between top-level elems and attrs
List elementNames = getElementNames(complexType);
List attributeNames = getAttributeNames(complexType);
attributeNames.retainAll(elementNames);
if (!attributeNames.isEmpty()) {
    // Report the name collision and return...
}
// Now check for any attribute wildcards, which we 
//  can't really change into elements
XSDWildcard attributeWildcard = complexType.getAttributeWildcard();
if (null != attributeWildcard) {
    // Report an incompatible wildcard and return...
}
// Check the content for other incompatible conditions like 
//  groups with choice or all or a simpleType
XSDComplexTypeContent complexTypeContent = complexType.getContent();
if (complexTypeContent instanceof XSDSimpleTypeDefinition) {
    // Report a simple type as incompatible and return...
}
else if (null != complexTypeContent)
{
    XSDTerm particleTerm = ((XSDParticle)complexTypeContent).getTerm();
    if (particleTerm instanceof XSDModelGroup)
    {
        XSDCompositor compositor = ((XSDModelGroup)particleTerm).getCompositor();
        if ((XSDCompositor.ALL_LITERAL == compositor)
                || (XSDCompositor.CHOICE_LITERAL == compositor)) {
            // Report an incompatible group type and return...
        }
    }
    // more checks for wildcards, etc.
}

 

注意:这里没有显示所有检查不匹配的代码。可以下载所有的样本 zip 文件(参见 参考资料),从中可以看到所有的过程。 MakeSoapCompatible.java 程序已经精心的设计,添加了详尽的注释,可以很清楚的了解如何处理 Model 中的 Schema 。如果您想学习更多内容,这是您的下一个目标。

 



 



创建元素声明

添加和处理组件的具体步骤


一旦您已经发现了那些您想更新的 complexType s ,您需要做一些具体的事情。对于每一个 complexType ,您需要该类型的具体属性列表 getAttributeContents() 。对于每一个属性,您要先确保您已经指向了属性的真实声明,那怕是指向了其他地方的声明。然后,您需要创建和属性具有相同名称和类型的 elementDeclaration ,这是一个非常直接的过程。您也需要将 elementDeclaration 加入到 getContents() 的新 Particle 中, 然后您将这个 particle 添加到您的 complexType

清单 3. 将属性更改为元素

if (attrDecl.isAttributeDeclarationReference())
    attrDecl = attrDecl.getResolvedAttributeDeclaration();
// Create a blank element and simply copy over the 
//  pertinent data about the attribute
XSDElementDeclaration elemDecl = XSDFactory.eINSTANCE.createXSDElementDeclaration();
elemDecl.setName(attrDecl.getName());
elemDecl.setTypeDefinition(attrType);
// Note that since an annotation's elements are only modeled 
//  in the concrete tree that we must explicitly ask to clone them
if (null != attrDecl.getAnnotation()) {
    cloneAnnotation(attrDecl, elemDecl);
}
// Wrap this element in a particle
XSDParticle particle = XSDFactory.eINSTANCE.createXSDParticle();
particle.setContent(elemDecl);

 

有一个地方很清楚地显示了抽象模型和具体模型之间的区别。当您查看您的 schemaDocument.xsd 文件的时候,您也许会想知道一个 particle 是什么,因为您没有看到任何 xsd:particle 元素。您可以阅读 specification for a particle ,这里介绍得相当详细。一个 particle 本质上是元素声明、模型组或者任意(通配符)的容器; particle 定义了 Schema 中特定地方的  min/maxOccurs 约束。因为 Model 可以显示 Schema 的具体和抽象表示,所以很容易和各种表示一起工作。

注释是另外一种 Schema 组件,只在模型的具体表示中建模,所以它们需要稍微特殊的处理。在样本代码中,您需要将属性声明中的任何注释复制到您所创建的新元素声明中。您使用 DOM cloneNode() 方法来执行注释组件中内容的复制操作,然后,将这些注释添加到新创建的元素声明中。

清单 4. 复制具体注释

XSDAnnotation oldAnnotation = attrDecl.getAnnotation();
XSDAnnotation newAnnotation = XSDFactory.eINSTANCE.createXSDAnnotation();
try {
    Element oldAnnElem = oldAnnotation.getElement();
    // Use the DOM method to do a deep clone of the element
    Element newAnnElem = (Element)oldAnnElem.cloneNode(true);
    newAnnotation.setElement(newAnnElem);
    elemDecl.setAnnotation(newAnnotation);
} 
catch (Exception e) {
    // Report the error and return
}





 



交换元素和属性

现在您已经创建了新的元素声明,用来替代您的属性。那么,您需要在您的 complexType 组件中交换这两者。因为在循环中您已经使用了 complexType.getAttributeContents() 的具体包容关系,您只需添加新的 elementDeclaration ,然后调用 attrContentsIter.remove() 来从您的类型中除去真正的属性。

清单 5. 使用具体列表来删除条目

// Use this concrete relationship, since we're going to 
//  actually remove the attributes from this type
for (ListIterator iter = 
        complexType.getAttributeContents().listIterator(); 
        iter.hasNext(); /* no-op */ ) {
    if (changeAttributeIntoElement(complexType, 
            (XSDAttributeGroupContent)iter.next(), changedAttrs)) {
        // Note that list manipulation calls like remove() 
        //  will only work properly on concrete lists; 
        //  attempting to manipulate 'abstract' lists will 
        //  either throw an exception or will silently fail
        iter.remove();
    }
    else {
        // Report the error and continue...
    }
}





 



输出 Schema

在执行 MakeSoapCompatible 样本程序的时候,会把它的状态输出到 System.out 。如果您检查到在 Schema 中没有用到属性,将报告没有进行更改,然后退出。否则的话,将修改过的 Schema 文档输出到新的文件,然后报告其状态——或者是一系列属性已经成功的更改为元素,或者提示说一些属性存在着命名冲突,尚未更改。

假定您已经将部分属性声明更改为对等的元素声明,您希望保存这些 Schema,以待在 SOAP 应用程序中使用。 用于构架 Model 的 EMF 框架提供了资源处理服务,可以使用多种方式来装载和保存 Schema 文档。在本样本代码中显示了一种简单的方法,直接把它序列化为 URI ,在这里其实就是以原始输入文件命名的硬盘输出文件。

清单 6. 将 Schema 输出到文件

File outFile = new File(newLocation);
FileOutputStream fos = new FileOutputStream(outFile);
// Ensure that the abstract model is synchronized with the 
//  concrete tree: this will ensure that the Model has 
//  updated the concrete Element in the schema document 
//  with any changes that may have been made in the 
//  abstract model
schema.updateElement();
// Simply ask the XSDResourceImpl to serialize the schema to 
//  a document for us; this is just one way we can easily use 
//  the XSD/EMF framework to manage resources for us
XSDResourceImpl.serialize(fos, schema.getElement());
fos.close();





 



结束语

如上所述,对 Schema 文档执行简单的编辑操作(将属性转换成为元素),需要一定的工作量。然而,Schema Infoset Model 可以显示 Schema 的抽象 Infoset 以及 Schema 文档的具体表示,这就使得这成为一个可管理的工作。 Model 也提供了简单的工具,用来装载和保存 Schema 文档为多种源文件。这样就提供了一个完整的管理 Schema 库的编程方案。

一些用户也许会问:“为什么比用 XSLT 或者其他 XML 处理程序来编辑 Schema 文档?”。实际上,虽然 XSLT 可以方便的处理 Schema 文档集的具体模型,它无法方便的看到它们所代表的整个 Schema 中的抽象关系。例如,您只想更新一个未知的新 UNK 枚举值中所包含的任意枚举 simpleType 。当然,您只想使用长度为三的字符串更新那些符合格式的枚举;您不想更新数值或者其他枚举。

虽然 XSLT 可以发现所有的 simpleType 声明,它无法理解这些类型和基本类型之间的关联,也无法方便的评估这些类型的含义。 Schema 中抽象 Infoset 关联的 Model 表示包含了 simpleType.getEffectiveEnumerationFacets() ,可以获得 Schema 中的类型、引用和其他关联。如果合适的话,它返回完整的 simpleType 枚举列表,可以方便的查询或者更新为新数值。

 



 



样本代码

本文提供了一个样本程序 MakeSoapCompatible.java ,显示了一个实例。任何有更多兴趣的人可以从那里阅读更清楚的注释。另外,也包含了一个简单的 Schema 文档 MakeSoapCompatible.xsd ,显示了一个基本的订单,其中的属性将转变为元素;对您的其他 Schema 文档也可以运行该样本程序。如果要独立运行,至少需要 XSD Schema Infoset Model 和 Eclipse Modeling Framework 。

您可以下载样本 Zip 文件中的样本程序和实用程序(参见 参考资料)。

在 XSD Schema Infoset Model(版本 1.0.1 或者更高版本)中通常附带了其他两个实用 .java 文件,其中附带注释的代码也显示了其他一些实用技术。它们包括:

XSDSchemaQueryTools.java 展示了其他查询 Schema 组件的高级方法。

XSDSchemaBuildingTools.java 有一些易用的方法,可以通过编程来构建 Schema 。

 

分享到:
评论

相关推荐

    C#XML入门经典 C#编程人员必备的XML技能.part2

    在.NET中使用XML&lt;br&gt;&lt;br&gt;3.1 XML如何适合.NET&lt;br&gt;3.1.1 XML&lt;br&gt;3.1.2 文档对象模型(DOM)&lt;br&gt;3.1.3 命名空间&lt;br&gt;3.1.4 DTD和XML Schema&lt;br&gt;3.1.5 XPath &lt;br&gt;3.1.6 XSLT&lt;br&gt;3.2 .NET Framework使用XML&lt;br&gt;3.2.1 配置...

    卓望提供的MISC彩信订购关系同步测试工具httptest

    &lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt; &lt;soap:Header&gt; &lt;TransactionID ...

    调用pb开发的webserver(SOAP 1.1)

    &lt;soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"&gt; &lt;soap12:Body&gt; &lt;uf_ab xmlns...

    w3c中文版(html5、css、ajax、asp、js、dhtml)

    http://www.wingtiptoys.com/help/" &lt;br&gt;另外微软自己的网站上也有类似的说明,网址是http://support.microsoft.com/kb/902225/zh-cn &lt;br&gt;它给的解决方法是引用 &lt;br&gt;为最终用户提供的解决方案 &lt;br&gt;警告:如果提示从...

    调用pb开发的webserver(SOAP 1.2)

    &lt;soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"&gt; &lt;soap12:Body&gt; &lt;uf_ab xmlns...

    值类型与引用类型理论内容.part05.rar

    ASP.NET培训资料(课堂视频含笔记)(AJAX,C#,JavaScript,SQL) &lt;br&gt;&lt;br&gt;我将不定期发布,直至所有课程完毕&lt;br&gt;&lt;br&gt;详细的资料&lt;br&gt;三个月的课程录像+资料笔记(花了一万六千块的培训资料超值【19G的经典内容】&lt;br&gt;认真...

    值类型与引用类型理论内容.part01.rar

    &lt;br&gt;精通C#.Net、ASP.Net、ADO.Net、AJAX、WEB2.0、XML、JavaScript、SQL&lt;br&gt;Server 2000、Web Service、WSE2.0、.Net Remoting、MultiThread&lt;br&gt;Programming、Socket Programming、Windows Service、Data Structure...

    WebService描述语言WSDL详解

    为什么使用WSDL? WSDL 文档结构 WSDL 文件示例 Namespaces SOAP 消息 XML schema运用于WSDL 的类型和消息中 XML schema运用之complex 类型 XML schema运用之数组 <portType >和<operation >元素...

    jQuery插件-JSON与XML互转

    支持XML转json; var mySoapXml ='&lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" '+ 'xmlns:xsd=... '&lt;/soap:Body&gt;' + '&lt;/soap:Envelope&gt;'; var json=$.xml2json(mySoapXml);

    Addison Wesley - Essential Xml Quick Reference (xml, Xpath, Xslt, Xml Schema, Soap And More)

    XML,SOAP和Web Service书

    SOAPy SOAP/XML Schema library for Python-开源

    SOAPy是用于Python的SOAP-1.1库,它使用WSDL和SDL文档来发现基于SOAP的服务API。 它还包括一个XML Schema解析器,该解析器可以解析XML Schema标准的子集。

    [XML][XML Schema 参考手册][GC.3.1].chm

    这个chm参考是说明了xml schema的节点等内容,做成chm格式方便查阅。

    mockito-soap-cxf:使用JUnit和Mockito测试SOAP服务

    Mockito-Soap-cxf SOAP Web服务模拟实用程序,使用Web服务器实例在本地端口上创建真实的服务端点。 这些端点将请求直接委托给模拟。 用户将从中受益 全栈客户端测试 ... &lt; artifactId&gt;mockito-soa

    Addison Wesley - Essential XML Quick Reference - A Programmer's Reference to XML, XPath, XSLT, XML Schema, SOAP and More.pdf

    XML家族那点东西都在这里了,Wesley的东西必然是精品无疑

    XML 讲解和分析

    XML ▪ XSL ▪ XSLT ▪ XSL-FO ▪ XPath ▪ XPointer ▪ XLink ▪ DTD ▪ XML Schema ▪ DOM ▪ XForms ▪ SOAP ▪ WSDL ▪ RDF ▪ RSS ▪ WAP ▪ Web Services Web脚本 JavaScript ▪ HTML DOM ▪ DHTML ▪ ...

    XMLSPY 2010 企业版

    xmlspy是符合行业标准的XML开发环境,专门用于设计,编辑和调试企业级的应用程序,包括XML, XML Schema, XSL/XSLT, SOAP, WSDL和互联网服务技术。这是J2EE,.NET和数据库开发人员不可缺少的高性能的开发工具。  最新...

    Altova XMLSpy2013简体中文版破解补丁

    &lt;Altova XMLSpy2013简体中文版破解补丁&gt; Altova XMLSpy是一款业界最畅销的XML编辑器,这款XMLSpy2013重点新增了智能修复、Java应用程序无缝集成、集成外部程序等新功能,而且本站提供的是中文破解版,能给用户带来极...

    webservice编写文档

    &lt;import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /&gt; &lt;import resource="classpath:META-INF/cxf/cxf-servlet.xml" /&gt; &lt;bean id="userServiceBean" class=...

    [XML入门经典(第4版)].(Beginning.XML.4th.Edition).(美)亨特,(美)拉夫特,(美)福思特.扫描版.pdf

    主要内容有XML基本语法、DTD、XML Schema、RELAX NG、XPath、XSLT、XQuery、DOM、SAX、RSS、Web服务、Ajax、SOAP、CSS、XHTML、SVG和XForms等,每章都有习题,书后附有参考答案,可帮助你全面掌握XML及其应用方法。...

    C#+XML+入门经典part2

    XML技术是近年来最热门的...主要内容包括:XML语法和格式良好的XML,XML命名空间,利用DTD和XML Schema进行XML验证,使用SOAP和Web服务,以及运用ADO.NET进行数据库访问等。本书还用两个案例分析来展示XML的具体应用。

Global site tag (gtag.js) - Google Analytics