我有一个简单的Java程序,如下所示,它读取一个xml文件并将其打印在控制台中:
FileInputStream in = new FileInputStream(new File("/tmp/test.xml"));
InputStreamReader streamReader = new InputStreamReader(in);
OMXMLParserWrapper builder = BuilderUtil.getBuilder(streamReader);
SOAPEnvelope envelope = (SOAPEnvelope)builder.getDocumentElement();
//the namespace prefix is OK here (java 7 and java 8)
System.out.println(envelope.getHeader().getChildrenWithLocalName("Ticket").next());
//but after the toString() method, the prefix has modified (java 7 = not change, java 8 = change)
//attribute mustUnderstand and role
System.out.println(envelope.toString());
XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<S:Header>
<abc:Ticket xmlns:abc="somevalue" xmlns:uebernehmeAbschlussdatenXBRL="abcSomevalue" S:mustUnderstand="true" S:role="http://www.w3.org/2003/05/soap-envelope/role/next">
<abc:value>long value</abc:value>
</abc:Ticket>
</S:Header>
<S:Body>
<sample>data</sample>
</S:Body>
</S:Envelope>
当我使用 woodstox-core-asl-4.4.1,stax2-api-3.1.4 和公理在Java 7中运行程序时,它运行正常。 但是当我在Java 8中运行相同的东西时,S:role和S:mustunderstand变为env:role和env:mustunderstand( S前缀变为env )
如果我从程序中删除 woodstox-core-asl-4.4.1 和 stax2-api-3.1.4 ,它在Java 8中也能正常工作
我无法弄清楚这个问题。这是否意味着woodstox不支持Java 8或我错过了其他什么?
答案 0 :(得分:2)
文档中的前缀S
和env
都映射到相同的名称空间URI http://www.w3.org/2003/05/soap-envelope
。
因此,即使序列化文档中的前缀发生了变化,它仍然等同于保留前缀的前缀。
(更改的原因可能是Java 8的DOM实现,类似于命名空间声明的不同排序。)
答案 1 :(得分:1)
这里要注意的一个基本事项是:使用envelope.toString()
并不是真正可靠的测试方法,因为目前还不清楚究竟是什么打印。 Woodstox不会更改报告的前缀,因此它不太可能暴露不同的前缀:更可能的情况是Axiom构建信封并将给定名称空间URI的映射回到不同的前缀,假设有2个选项。
所以:我猜这是因为JDK更改与String哈希代码计算或HashMap条目的排序有关。假设存在2个具有不同前缀的等效命名空间,当Axiom请求给定命名空间URI的前缀时,两者的排序可能导致不同的匹配;毕竟,BOTH映射到相同的前缀,并且由于属性的排序(其名称空间前缀声明是特殊情况)在XML中是未定义的(即,没有排序),其中一个是有效的
如果没有Woodstox依赖,处理可能使用JDK嵌入式Stax解析器(sjsxp),并且对它进行排序可能是意外稳定的,或者使用非基于散列的机制。
答案 2 :(得分:0)
意外的前缀是由旧版本的Apache Axiom(1.2.11超过5年)中的问题引起的。您应该升级到1.2.15或更高版本。
Axiom曾经使用HashMap
来存储名称空间声明;这可能是给定消息的原因,您只能看到某些Java版本的问题。