Namespace Support

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

<?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 Expressions

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

所有形式的 XPath 表达式都会创建一个使用 Spring org.springframework.xml.xpath.XPathExpressionFactoryXPathExpression。在创建 XPath 表达式时,会使用在类路径上可用的最佳 XPath 实现(JAXP 1.3+ 或 Jaxen,首选 JAXP)。

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

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

<int-xml:xpath-expression expression="" 1
          id=""                         2
          namespace-map=""              3
          ns-prefix=""                  4
          ns-uri="">                    5
    <map></map>                         6
</int-xml:xpath-expression>
1 Defines an XPath expression. Required.
2 基础 Bean 定义的标识符。它是 org.springframework.xml.xpath.XPathExpression 的一个实例。可选。
3 对包含名称空间的映射的引用。映射的键定义名称空间前缀,映射的值设置名称空间 URI。不能同时指定此属性及 map 元素或 ns-prefixns-uri 属性。可选。
4 允许您将名称空间前缀直接设为 XPath 表达式元素上的一个属性。如果您设置了 ns-prefix,您还必须设置 ns-uri 属性。可选。
5 允许您直接将名称空间 URI 设为 XPath 表达式元素上的一个属性。如果您设置了 ns-uri,您还必须设置 ns-prefix 属性。可选。
6 定义包含名称空间的映射。仅允许有一个 map 子元素。映射的键定义名称空间前缀,映射的值设置名称空间 URI。不能同时指定此元素及 map 属性或设置 ns-prefixns-uri 属性。可选。

Providing Namespaces (Optional) to XPath Expressions

对于 XPath 表达式元素,可以提供命名空间信息作为配置参数。可以使用以下选项之一来定义命名空间:

  • 使用 namespace-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>

Using XPath Expressions with Default Namespaces

在使用默认命名空间时,可能会遇到与预期有差异的行为。假设有以下 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) 在这种情况下失败了。

为了解决此问题,您必须提供命名空间前缀和命名空间 URI,可以通过设置 ns-prefixns-uri 属性或设置 namespace-map 属性来实现。命名空间 URI 必须与 XML 文档中声明的命名空间匹配。在上述示例中,即 http://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 很好地总结了这一要点:

In XPath 1.0, all unprefixed names are unqualified. There is no requirement that the prefixes used in the XPath expression are the same as the prefixes used in the document being queried. Only the namespace URIs need to match, not the prefixes.