XML相关的规范几乎都使用namespace限定XML数据.由于namespace有很多微妙的细节,如果对这些微妙的细节不能有清晰的把握,往往会导致一些难以理解的错误。在这里我把个人遇到的一些问题进行了一下归纳。分为以下几个方面:
1)xml namespace的基本问题:
这一部分描述了namespace的基本知识以及一些微妙的细节,是最为基础和关键的部分。其他部分不过是其他扩展使用而已。黑色字体标注出了较为微妙的问题的标题。
2)Schema中对namespace使用
3)XPath中的namespace使用
4)Webservice的namespace注意问题
1:XML的namespace的基本问题
1.1:xml元素的限定名(QName)
大多数xml初学者一开始接触xml时,被灌输的xml元素名都是非限定名称。这也是导致我们经常在namespace问题上犯错误的根本原因。
使用限定名的示例:
<ns:Book xmlns:ns="http:// publication"/>
xml元素为限定名,包括两个部分:namespace + localPart;
上述例子中namespace的为 "http:// publication", localPart为Book。
打个比方,namespace的作用是将不同的xml元素划分为不同的集合。集合的名称就是namespace的uri值。 元素自己的名称就是集合内的名称。所以判定2个xml元素的名称一样的条件必须是:xml元素所属集合(namespace) 以及集合内的名字(xml元素自己的名字)都一样。
1.1.1:如何在QName的框架下,理解非限定名?
下面是一个与我们最初接触的xml类似的示例.
<book>.....</book>
这样一个例子就是非限定名称的xml元素。那么在限定名称(QName)的框架下如何理解非限定名称呢? 我们可以把非限定名的xml元素理解为 namespace的uri值为""(空串,以后我们简述为空), localPart=xml元素名。换句话说,非限定名 是namespace的uri值为空的QName的特殊称谓。
后面我们会进一步描述这种情况的一些微妙细节。
1.2:xml中 如何定义和使用namespace
基本规则如下:
a)使用形式为xmlns:prefix="uri"的特殊xml属性定义namespace
b)在元素名称前使用 prefix:来修饰元素名,表示元素QName的namespace
示例:<ns:Book xmlns:ns="http:// publication "/>
ns: 是prefix. 表示uri(http://publish/a)的缩写
ns:Book:是对Book的修饰。表示Book位于名字空间”http://publish/a。
prefix可以省略,但省略后会引发一些微妙的问题,后面我们会详细描述这种情况
prefix只是指代namespace的一个缩略词,本身没有任何实际的意义。所以缩略词是什么,根本不影响xml数据的实际意义。
示例:
<ns:Book xmlns:ns=”http://publication”/>
<pub:Book xmlns:pub="http://publication”/>
虽然看上去不太一样,这两个XML数据完全等价。
这意味着,我们写程序判断两个xml是否相等时,不能只是简单的判断xml的元素名是否相同,而必须判断QName是否相同。如何正确的获取xml的QName取决与我们所使用的具体的XML 数据访问API。对于w3c接口,getNamespace(), getLocalName()方法不总是有效,请注意正确的设置DocumentBuilderFactory的namespaceAware属性
1.3:namespace定义的作用域
默认情况下,
namespace的定义的作用域是当前元素以及所有的子/孙元素。除非子元素使用相同的prefix重新定义了namespace
注意:namespace的定义和引用是两回事情。定义namespace的地方不一定马上使用此namespace
示例1
A元素定义了2个namespace,ns的namespace没有马上使用。而是在子/孙元素中才使用.
< org:A xmlns:org ="http://publish-org" xmlns:ns="http://publication"/>
<ns:Book>
<ns:Name>xxxx</ns:Name>
</ns:Book>
</org:A>
示例2:Book子元素覆盖了A父元素的“ns”的namespace定义。这个示例的xml与前述示例的xml数据完全等价。
<ns:A xmlns:ns="http://publish-org">
<ns:Book xmlns:ns="http://publication">
<ns:Name>xxxx</ns:Name>
</ns:Book>
</ns:A>
1.4:默认的名字空间与未限定名称的XML?
a) 什么是默认的名字空间?
定义namespace时,prefix可以省略,这样的名字空间为默认名字空间。因为此时声明xml元素名时,不需要使用前缀就表示该元素名称受到该名字空间的限定。同样的默认名字空间也可以被子元素继承或者重载
示例1:
<book xmlns=”http://publication”/>
book受默认namespace(http://publication)的限定。
示例2:
<org:A xmlns:org ="http://publish-org" xmlns="http://publication"/>
<book> …</book>
</org:A>
book元素继承了来自父元素的默认名字空间,所以名称受到此默认namespace(http://publication)的限定
b) “茴”字的七种写法——未限定XML的限定书写方式
我们前面提到,在限定名(QName)的技术框架下,可以将非限定名理解为namespace的uri值为空的限定名(QName)。
这意味着我们可以使用声明namespace的方式来书写等价的非限定XML元素。下面给出了3个XML。其中第一个是常规的非限定写法。而后两个则是等价的限定书写方式。
<book>
<name>xxx</name>
</book>
<ns:book xmlns:ns=””>
<ns:name>xxx</ns:name>
</ns:book>
<!--请特别注意这个写法与常规的非限定写法的区别-->
<book xmlns=””>
<name>xxx</name>
</book>
我们不想做孔乙己,可是现实很无奈
c) 默认的名字空间与非限定名一起使用时,要特别注意他们的区别。
为了说明这个问题,我们看看以下4个xml。这4个xml数据的前两个等价,后两个等价。
1)
<ns:book xmlns:ns=”http://publication”>
<ns:name>xxx</ns:name>
</ns:book>
book,name元素都受到http://publication名字空间的限定。
2)<book xmlns=”http://publication”>
<name>xxx</name>
</book>
book,name元素都受到http://publication名字空间的限定(默认名字空间的方式)。
3)
<ns:book xmlns:ns=”http://publication”>
<name>xxx</name>
</ns:book>
book受到http://publication名字空间的限定,name元素不受限定。
4)
<book xmlns=”http://publication”>
<name xmlns=””>xxx</name>
</book>
book受到http://publication名字空间的限定,name元素不受限定。
由于book元素定义了默认名字空间,所以name元素必须显示定义uri为空的名字空间,来强制声明自己是不受到namespace限定的。
,是不是比较变态。但这种变态的情况往往会在使用XML Schema技术时出现,下面我们会详细描述。并且很多技术(譬如Webservice引擎)没有正确的处理这种情况,会导致一些微妙的bug
1.5)XML 属性的QName
Xml属性的名称与xml元素的名称一样,也会受到namespace的限定。用于属性的QName的规则与前面描述的xml元素QName的规则基本一致。除了以下1条例外规则:
xml属性的名称必须显示的使用prefix进行限定,不会自动受到默认名字空间的限定。
示例1:
<book xmlns=”http://publication” name=”xxx”/>
虽然定义了默认名字空间(http://publication),但属性"name"不受默认名字空间的限定。
示例2:
<ns:book xmlns:ns=”http://publication” ns:name=”xxx”/>
通过prefix的方式强制指定name属性受到namespace(http://publication)限定
1.6)进一步了解namespace的资料
http://www.w3.org/TR/REC-xml-names/
2)Schema中对namespace使用
2.1)元素名qualified/unqualified的区别
schema中可以使用elementFormDefault来限定xml元素名称为qualified还是unqualified。其作用规则如下:
a)schema中直接定义的xml 元素名不受到qualified/unqualified的影响。总是schema的targetNamespace所定义的namespace的限定。
“直接定义”只是一个形象的说法,我们可以参见下面的示例来区分直接定义的含义。
备注:本文中统一使用xs的prefix指代schema规范的namespace,譬如<xs:schema>表示是一个符合schema规范的schema元素(定义一组xml类型与元素)。
targetNamespace是schema元素的属性,属性值是一个namespace的uri值。主要描述1: schema内直接定义的xml元素(<xs:element>),其名称都受到targetNamespace的指定的namespace的限定。2:schema内定义的类型(<xs:type>)的名称也都受到targetNamespace的指定的namespace的限定
b)schema的xs:type中定义的子元素,其元素名受到qualified/unqualified的影响。
当qualified,表示子元素的名称受到namespace的限定,位于schema的targetNamespace所规定的namespace内。
取值为unqualified,表示子元素的名称不受namespace的限定,即子元素的定义在uri为空的名字空间内。
示例1:qualified示例
<xs:schema xmlns:xs="http://www.w3.org/XML_Schema"
elementFormDefault="qualified" targetNamespace="http://publication">
<xs:element name="book">
<xs:type><xs:sequence>
<xs:element name="name " type="xs:string"/>
</xs:sequence></xs:type>
</xs:element >
</xs:schema>
此schema定义了2个xml元素。其中book子元素是直接元素。name则不是直接元素。
所以book元素不会收到qualified/unqualified的影响。总是会受到schema的targetNamespace的限定。
而name元素则会受到qualified/unqualified影响。在本示例中,因为是qualified,所以name是受到targetNamespace限定的。
符合上述schema定义的合法xml如下:
<ns:book xmlns:ns="http://publication"/>
<ns:name>xxx</ns:name>
</ns:book>
示例2:unqualified
此示例的schema与上述示例的schema基本一样,唯一区别是elementFormDefault属性的值为unqualified。unqualified,所以name不受http://publication的限定;
合法的xml是:
<ns:book xmlns:ns="http://publication"/>
<name >xxx</name >
</ns:book >
再次提醒:如果实际的xml元素使用了默认名字空间,内部子元素一定要注意qualified和unqualified的区别。必要时,必须在子元素上显示声明uri=””的名字空间,表示xml元素不受到namespace的限定
示例:qualified的另外一种合法写法。
<book xmlns="http://publication"/>
<name>xxx</name>
</book>
示例:unqualified的另外一种合法写法。
<book xmlns="http://publication"/>
<name xmlns=””>xxx</name>
</book>
schema定义的直接XML元素会受到schema的targetNamespace的限定,但不意味着schema直接定义的xml元素的总是namespace受限定的。因为schema可以不定义targetNamespace,此时等价于targetNamespace指定为空。此时schema定义的直接xml元素名受到uri值为空的namespace的限定等同于不限定xml元素名
2.3)元素属性名称qualified与unqualified的区别
schema元素的attributeFormDefault属性可以取值qualified/unqualified。其功能与elementFormDefault类似,只不过用于描述属性名是限定/非限定方式。
通常属性都是使用unqualified,很少特意指定为qualified。我们在xml namespace的基本问题中提到过,除非显示指定,属性名称不会受到默认名字空间的限定。所以这种用法不会象xml元素名那样,因为定义了默认名字空间而导致微妙的错误。
3)XPath中的namespace使用
我们在书写xpath表达式中的元素名时,如果只是简单的书写元素名。xpath总是理解为"这是一个不受namespace限定的元素名";假设我们有以下XML
<book xmlns="http://publication">
<name>xxx</name>
</book>
我们通过名称"book"是根本无法匹配book元素的。因为xpath理解为book是一个不受限定的名称。而实际的xml,book是受到http://publication限定的。
此时我们必须使用prefix:name的书写格式告诉xpath,这是一个受到namespace限定的名称。所以我们需要处理
3.1)如何将前缀与namespace uri的对应关系告诉xpath引擎。
取决与具体使用的XPath引擎。jdk标准的xpath接口,可以参阅
a)javax.xml.xpath.XPath.setNamespaceContext()
b)javax.xml.namespace.NamespaceContext:定义prefix与uri的映射关系。
只需要实现自己的NamespaceContext接口,并调用setNamespaceContext通知xpath引擎即可。
3.2)使用时可以使用我们定义的前缀+ ":"+ 元素名来匹配QName;
假设我们通知xpath引擎, prefix("ns")对应uri("http://publication")。那么我们可以在xpath中使用名称 ns:book来匹配上述xml元素。
4)Webservice的namespace注意问题
4.1)注意qualified/unqualified schema引发的bug
由于webservice基于schema技术实现,因此会遇到qualified/unqualified的schema定义的不同情况。但主要问题在于,很多webservice引擎(尤其是老版本的开源webservice引擎, cxf, axis2, xfire都有类似情况)在处理数据对象到xml转换时,在特殊情况下会使用默认名字空间。此时,容易导致内部子元素错误的受到默认名字空间的限定。从而导致:虽然schema是unqualified,但实际的xml数据却错误的变成了qualified。从而导致webservice调用失败。
对于这种情况,建议找到你所使用webservice引擎处理数据对象的xml映射的规律,总是强迫其不使用默认名字空间。这样会避免错误。譬如CXF的老版本可以在根据wsdl生成java数据对象时,强迫java数据对象类的package与namespace uri不一致。这样可以避免使用默认名字空间
4.2)注意XML namespace继承引发的bug
按照xml namespace的基本规则,父元素定义的namespace会被子元素自动继承。
这样有些ws引擎可能会将xml数据对象用到的namespace定义在soap:Envelope, soap:Body, soap:Header 这些soap协议的标准xml元素上。
譬如:
<soap:Envelope xmlns:ns="http://publication">
<soap:Body>
<ns:Book>
......
</ns:Book>
</soap:Body>
</soap:Envelope>
但是问题在于,虽然这样使用是符合xml namespace规范的,但是由于webservcie引擎在解析soap协议栈时,是分模块的。因此可能会导致在处理用户的xml数据时,无法正确的找到soap 标准xml(envelop, body, header)上声明的xml namespace。从而导致错误发生。
关于这个问题,没有特别好的解决方法,需要注意更新所使用的webservice引擎的实现。这通常会作为bug被较新的版本解决。
分享到:
相关推荐
python xml命名空间 The ns0: prefix for an element name is a reference to a (XML) NameSpace.
XML的命名空间
解决javax.xml jar包缺失的问题,引进javax.xml.rpc-api-1.1.1.jar
解压后先修改generator.xml相关信息,然后用cmd命令行使用,内有详细操作说明
xml转javaBean,javaBean转xml,xml标签大小写问题,CDATA的生成,以及对xml特殊符号的处理
使用java工具xml2axml.jar反编译AndroidManafest文件 通过xml2axml.jar工具反编译AndroidManafest文件 还原AndroidManafest.xml详细过程: 1、获取到apk 2、解压获取里面的AndroidManifest.xml文件 3、在xml2axml....
Dom4j解析XML及中文问题Dom4j解析XML及中文问题Dom4j解析XML及中文问题Dom4j解析XML及中文问题Dom4j解析XML及中文问题Dom4j解析XML及中文问题
xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml 查询问题 急xml ...
xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作xml操作
weblogic javax/xml/namespace/QName报错-附件资源
java在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava...
关于XML相对路径问题,包括:1.相对路径(根目录,上级目录,三级目录,四级目录),2.获取和设置当前目录的完全限定路径,3.获取和设置包含该应用程序的目录的名称,4.获取启动了应用程序的可执行文件的路径,包括可...
书中的主题如下: *XML基础,包括DTD、命名空间(namespace)、XML Schema和数据格式转换 (Transformation) *SAX应用程序编程接口,包括处理器接口、过滤器接口和写出接口 *DOM应用程序编程接口,...
XML文件解析问题.pdf
tinyxml与tinyxml2两个版本的源码,操作xml很方便,解压可以直接使用.
DIXml is an embedded XML, XSLT, and EXSLT processing ...NameSpace support. XSLT transformation and processing. File, memory, and customized input / output. Low memory usage, outstanding performance.
无废话XML 无废话XML 无废话XML 无废话XML 无废话XML
Helper APIs to assist with programming for XML namespace or the HyperText Transfer Protocol (HTTP) when it is used to send data directly between Web servers. The XML Data Reduced schema definition ...
动态生成Rss文件 Xml操作 Xml文件的修改动态生成Rss文件 Xml操作 Xml文件的修改动态生成Rss文件 Xml操作 Xml文件的修改动态生成Rss文件 Xml操作 Xml文件的修改动态生成Rss文件 Xml操作 Xml文件的修改动态生成Rss文件...