命名空间支持

Spring Integration XML 模块中的所有组件都提供命名空间支持。 为了启用命名空间支持,你需要导入 Spring Integration XML 模块的 Schema。 以下示例展示了一个典型的设置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"
  xmlns:int-xml="http://www.springframework.org/schema/integration/xml"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration
    https://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/xml
    https://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd">
</beans>

XPath 表达式

Spring Integration XML 模块中的许多组件都使用 XPath 表达式。 这些组件中的每一个要么引用一个已定义为顶级元素的 XPath 表达式,要么使用嵌套的 <xpath-expression/> 元素。

所有形式的 XPath 表达式都会导致创建 XPathExpression,它使用 Spring 的 org.springframework.xml.xpath.XPathExpressionFactory。 创建 XPath 表达式时,将使用类路径上可用的最佳 XPath 实现(JAXP 1.3+ 或 Jaxen,JAXP 优先)。

在内部,Spring Integration 使用 Spring Web Services 项目提供的 XPath 功能([role="bare"][role="bare"][role="bare"]www.spring.io/spring-ws)。 具体来说,我们使用 Spring Web Services XML 模块(spring-xml-x.x.x.jar)。 如需深入了解,请参阅 [role="bare"][role="bare"][role="bare"]docs.spring.io/spring-ws/docs/current/reference/#xpath 上的相关文档。

以下是 xpath-expression 元素所有可用配置参数的概述: 以下列表显示了 xpath-expression 元素的可用属性:

<int-xml:xpath-expression expression="" [id="CO1-1"]1
          id=""                         [id="CO1-2"]2
          namespace-map=""              [id="CO1-3"]3
          ns-prefix=""                  [id="CO1-4"]4
          ns-uri="">                    [id="CO1-5"]5
    <map></map>                         [id="CO1-6"]6
</int-xml:xpath-expression>
 <1>  定义一个 XPath 表达式。
必填。
 <1>  底层 bean 定义的标识符。
它是 `org.springframework.xml.xpath.XPathExpression` 的一个实例。
可选。
 <1>  引用一个包含命名空间的 map。
map 的键定义命名空间前缀,map 的值设置命名空间 URI。
不能同时指定此属性和 `map` 元素或 `ns-prefix` 和 `ns-uri` 属性。
可选。
 <1>  允许你直接在 XPath 表达式元素上将命名空间前缀设置为属性。
如果设置 `ns-prefix`,则还必须设置 `ns-uri` 属性。
可选。
 <1>  允许你直接在 XPath 表达式元素上将命名空间 URI 设置为属性。
如果设置 `ns-uri`,则还必须设置 `ns-prefix` 属性。
可选。
 <1>  定义一个包含命名空间的 map。
只允许一个 `map` 子元素。
map 的键定义命名空间前缀,map 的值设置命名空间 URI。
不能同时指定此元素和 `map` 属性或设置 `ns-prefix` 和 `ns-uri` 属性。
可选。

为 XPath 表达式提供命名空间(可选)

对于 XPath 表达式元素,你可以将命名空间信息作为配置参数提供。 你可以通过以下任一选项定义命名空间:

  • 使用 namespace-map 属性引用一个 map

  • 使用 map 子元素提供一个命名空间 map

  • 指定 ns-prefixns-uri 属性

所有这三个选项都是互斥的。 只能设置其中一个选项。

以下示例展示了几种使用 XPath 表达式的不同方式,包括设置 XML 命名空间的选项(xpath-namespace-support):

<int-xml:xpath-filter id="filterReferencingXPathExpression"
                      xpath-expression-ref="refToXpathExpression"/>

<int-xml:xpath-expression id="refToXpathExpression" expression="/name"/>

<int-xml:xpath-filter id="filterWithoutNamespace">
    <int-xml:xpath-expression expression="/name"/>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithOneNamespace">
    <int-xml:xpath-expression expression="/ns1:name"
                              ns-prefix="ns1" ns-uri="www.example.org"/>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithTwoNamespaces">
    <int-xml:xpath-expression expression="/ns1:name/ns2:type">
        <map>
            <entry key="ns1" value="www.example.org/one"/>
            <entry key="ns2" value="www.example.org/two"/>
        </map>
    </int-xml:xpath-expression>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithNamespaceMapReference">
    <int-xml:xpath-expression expression="/ns1:name/ns2:type"
                              namespace-map="defaultNamespaces"/>
</int-xml:xpath-filter>

<util:map id="defaultNamespaces">
    <util:entry key="ns1" value="www.example.org/one"/>
    <util:entry key="ns2" value="www.example.org/two"/>
</util:map>

使用带有默认命名空间的 XPath 表达式

在使用默认命名空间时,你可能会遇到行为与预期不同的情况。 假设我们有以下 XML 文档(表示两本书的订单):

<?xml version="1.0" encoding="UTF-8"?>
<order>
    <orderItem>
        <isbn>0321200683</isbn>
        <quantity>2</quantity>
    </orderItem>
    <orderItem>
        <isbn>1590596439</isbn>
        <quantity>1</quantity>
    </orderItem>
</order>

此文档未声明命名空间。 因此,应用以下 XPath 表达式按预期工作:

<int-xml:xpath-expression expression="/order/orderItem" />

你可能期望相同的表达式也适用于以下 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<order xmlns="http://www.example.org/orders">
	<orderItem>
		<isbn>0321200683</isbn>
		<quantity>2</quantity>
	</orderItem>
	<orderItem>
		<isbn>1590596439</isbn>
		<quantity>1</quantity>
	</orderItem>
</order>

前面的示例与上一个示例完全相同,但声明了一个默认命名空间。

然而,前面的 XPath 表达式(/order/orderItem)在这种情况下会失败。

为了解决这个问题,你必须通过设置 ns-prefixns-uri 属性,或者通过设置 namespace-map 属性来提供命名空间前缀和命名空间 URI。 命名空间 URI 必须与你的 XML 文档中声明的命名空间匹配。 在前面的示例中,它是 www.example.org/orders

但是,你可以随意选择命名空间前缀。 实际上,提供一个空字符串实际上是可行的。 (但是,不允许为 null。) 在命名空间前缀由一个空字符串组成的情况下,你的 Xpath 表达式必须使用冒号(":")来指示默认命名空间。 如果你省略冒号,XPath 表达式将不匹配。 以下 XPath 表达式匹配前面示例中的 XML 文档:

<int-xml:xpath-expression expression="/:order/:orderItem"
    ns-prefix="" ns-uri="https://www.example.org/prodcuts"/>

你还可以提供任何其他随意选择的命名空间前缀。 以下 XPath 表达式(使用 myorder 命名空间前缀)也匹配:

<int-xml:xpath-expression expression="/myorder:order/myorder:orderItem"
    ns-prefix="myorder" ns-uri="https://www.example.org/prodcuts"/>

命名空间 URI 是真正重要的信息,而不是前缀。 Jaxen 很好地总结了这一点:

在 XPath 1.0 中,所有无前缀名称都是无限定的。 XPath 表达式中使用的前缀与被查询文档中使用的前缀不必相同。 只有命名空间 URI 需要匹配,而不是前缀。