当您使用任何类型的XML工具时,至少有三点需要考虑:
-
任何XML文档都有字符编码
-
有不同的方法可以将XML文档映射到类(文字或SOAP编码)
-
您应该知道SAX解析器的默认行为
2.1 输入和输出的字符编码
导出XML文档时,可以指定要使用的字符编码;否则,InterSystems IRIS会根据目的地选择编码:
- 如果输出目的地是文件或二进制流,则默认值为“UTF-8”。
- 如果输出目的地是字符串或字符流,则默认为“UTF-16”。
对于InterSystems IRIS读取的任何XML文档,文档的XML声明应该指示该文件的字符编码,并且文档应该按照声明进行编码。例如:
<?xml version="1.0" encoding="UTF-16"?>
但是,如果文档中没有声明字符编码,则InterSystems IRIS假设如下:
- 如果文档是文件或二进制流,InterSystems IRIS会假定字符集为“UTF-8”。
- 如果文档是字符串或字符流,InterSystems IRIS会假定字符集为“UTF-16”。
有关InterSystems IRIS中字符翻译的背景信息,请参阅服务器端编程方向指南中的本地化支持。
2.2 选择文档格式
当您使用XML文档时,您必须知道将文档映射到InterSystems IRIS类时要使用的格式。类似地,当您创建XML文档时,您可以指定在编写文档时要使用的文档格式。XML文档格式如下:
-
字面意思是文档是对象实例的字面副本。在大多数情况下,您使用文字格式,即使在使用SOAP时也是如此。
除非另有说明,否则文档中的示例使用文字格式。
-
编码是指按照SOAP 1.1标准或SOAP 1.2标准所述进行编码。有关这些标准的链接,请参见XML标准。
SOAP 1.1和SOAP 1.2的细节略有不同。
以下小节显示了这些文档格式之间的差异。
2.2.1 文字格式
以下示例显示了一个文本格式的XML文档:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Person>
<Name>Klingman,Julie G.</Name>
<DOB>1946-07-21</DOB>
<GroupID>W897</GroupID>
<Address>
<City>Bensonhurst</City>
<Zip>60302</Zip>
</Address>
<Doctors>
<DoctorClass>
<Name>Jung,Kirsten K.</Name>
</DoctorClass>
<DoctorClass>
<Name>Xiang,Charles R.</Name>
</DoctorClass>
<DoctorClass>
<Name>Frith,Terry R.</Name>
</DoctorClass>
</Doctors>
</Person>
</Root>
2.2.2 编码格式
相比之下,以下示例以编码格式显示了相同的数据:
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
<DoctorClass id="id2" xsi:type="DoctorClass">
<Name>Jung,Kirsten K.</Name>
</DoctorClass>
...
<DoctorClass id="id3" xsi:type="DoctorClass">
<Name>Quixote,Umberto D.</Name>
</DoctorClass>
...
<DoctorClass id="id8" xsi:type="DoctorClass">
<Name>Chadwick,Mark L.</Name>
</DoctorClass>
...
<Person>
<Name>Klingman,Julie G.</Name>
<DOB>1946-07-21</DOB>
<GroupID>W897</GroupID>
<Address href="#id17" />
<Doctors SOAP-ENC:arrayType="DoctorClass[3]">
<DoctorClass href="#id8" />
<DoctorClass href="#id2" />
<DoctorClass href="#id3" />
</Doctors>
</Person>
<AddressClass id="id17" xsi:type="s_AddressClass">
<City>Bensonhurst</City>
<Zip>60302</Zip>
</AddressClass>
...
</Root>
请注意编码版本中的以下差异:
-
输出的根元素包括SOAP编码命名空间和其他标准命名空间的声明。
-
此文档包括同一级别的人员、地址和医生元素。地址和医生元素以引用它们的个人元素所使用的唯一ID列出。每个对象值属性都是这样处理的。
-
顶级地址和doctor元素的名称与相应类的名称相同,而不是与引用它们的属性的名称相同。
-
编码格式不包括任何属性。GroupID属性被映射为Person类中的一个属性。在文字格式中,此属性被投影为属性。然而,在编码版本中,属性被投影为一个元素。
-
集合有不同的处理方式。例如,列表元素具有属性ENC:arrayType。
-
每个元素都有一个xsi:type属性的值。
注:
对于SOAP 1.2,编码版本略有不同。要轻松区分版本,请检查SOAP编码命名空间的声明:
- 对于SOAP 1.1,SOAP编码命名空间为“http://schemas.xmlsoap.org/soap/encoding/
- 或SOAP 1.2,SOAP编码命名空间为“http://schemas.xmlsoap.org/wsdl/soap12/"
2.3 分析器行为
每当InterSystemsIRIS读取XML文档时,都会使用InterSystems IRSI SAX Parser,因此了解其默认行为是很有用的。在其他任务中,解析器执行以下操作:
-
它验证XML文档的格式是否正确。
-
它试图使用给定的模式或DTD来验证文档。
这里需要记住的是,模式可以包含引用其他模式的<import>和<include>元素。例如:
<xsd:import namespace="target-namespace-of-the-importing-schema" schemaLocation="uri-of-the-schema"/> <xsd:include schemaLocation="uri-of-the-schema"/>
除非解析器可以使用这些其他模式,否则验证将失败。特别是对于WSDL文档,有时需要下载所有模式并编辑主模式以使用正确的位置。
-
它试图解析所有实体,包括所有外部实体。(其他XML解析器也会这样做。)这个过程可能很耗时,具体取决于它们的位置。特别是,Xerces使用网络访问器来解析一些URL,并且实现使用阻塞I/O。因此,没有超时,网络获取可能会在错误条件下挂起,这在实践中是罕见的。
此外,Xerces不支持https;也就是说,它无法解析位于https位置的实体。
如果需要,可以创建自定义实体解析程序,也可以禁用实体解析。