我可以依赖int-xml:xpath-splitter
输出的消息的顺序吗?
我正在使用:
示例:
给出以下XML文档:
<?xml version="1.0" encoding="UTF-8"?>
<tests>
<test>test</test>
<test>test2</test>
</tests>
以下int-xml:xpath-splitter
:
<int-xml:xpath-splitter id="messageSplitter"
input-channel="inbound"
output-channel="routing"
create-documents="false">
<int-xml:xpath-expression expression="/*/*"/>
</int-xml:xpath-splitter>
<int:channel id="routing">
<int:queue/>
</int:channel>
routing
渠道始终会在<test>test</test>
之前收到<test>test2</test>
吗?
答案 0 :(得分:2)
我相信这个问题的答案取决于您使用的是哪个JAXP提供商。
如果您已配置支持XPath 2.0的XPath引擎;然后是的,消息将按文档顺序排列。
如果使用默认或XPath 1.0引擎;然后不,订单不能保证 1 。
XPath 1.0不是 1 ,XPath 2.0。
根据XPath 1.0规范,XPath 1.0表达式返回node-set
个类型,node-set
类型是无序的:
XPath中的主要句法结构是表达式。表达式与生产Expr匹配。计算表达式以生成一个对象,该对象具有以下四种基本类型之一:
- node-set(没有重复的无序节点集合)
- 布尔值(true或false)
- 数字(浮点数)
- string(一系列UCS字符)
另一方面,XPath 2.0规范引入了document order:
的概念文档顺序是总排序,尽管某些节点的相对顺序依赖于实现。 [定义:非正式地,文档顺序是节点在文档的XML序列化中出现的顺序。] [定义:文档顺序是稳定的,这意味着在处理给定表达式期间两个节点的相对顺序不会改变,即使这个顺序依赖于实现。]
规范还指出,Path Expressions的评估按文档顺序返回节点序列:
E2的所有评估得到的序列如下组合:
如果E2的每个评估返回(可能是空的)节点序列,则组合这些序列,并且基于节点标识消除重复节点。生成的节点序列按文档顺序返回。 如果E2的每个评估返回一个(可能是空的)原子值序列,则按顺序连接这些序列并返回。 如果E2的多次评估返回至少一个节点和至少一个原子值,则会引发类型错误[错误:XPTY0018]。
Spring使用javax.xml.xpath.XPathFactory.newInstance(String uri)创建一个用于创建XPath
个对象的XPathFactory。 JavaDoc详细解释了XPathFactory.newInstance(uri)
的行为方式,但足以说它在项目中搜索适当的工厂。
如果您的项目没有以不同的方式指定,Spring将使用JAXP 1.3实现来创建XPath表达式。
从Java 1.6开始,JAXP 1.3 only supports XPath 1.0。
请参阅您正在使用的XPathFactory的文档。
就我而言,我的项目设置了Saxon-HE-9.4.0-9。撒克逊人implements the JAXP 1.3 API and Supports XPath 2.0。
how XPath's are evaluated的Saxon文档未明确声明NODESET
表达式将按文档顺序返回。但是,它确实声明返回对象是Java List对象。
基于XPath 2.0表达式按文档顺序返回节点的事实,Saxon支持XPath 2.0,Saxon返回一个Java List对象(有序),我认为Saxon将按文档顺序返回节点。
xpath-splitter
的邮件也是文档顺序吗?是的,他们会;基于org.springframework.integration.xml.splitter.XPathMessageSplitter.splitMessage(Message<?>)
中代码的我的分析。
splitDocument(document)
和splitNode(Node node)
都保留了从评估XPath表达式返回的List的顺序。
<子> 1。正如Michael Kay在他的评论和answer on another question中所指出的,虽然XPath 规范不保证顺序,但实际上XPath 1.0的实现通常也支持XSLT 1.0并且将返回节点文档顺序,因为XSLT需要它。