(window.webpackJsonp=window.webpackJsonp||[]).push([[507],{944:function(e,r,t){"use strict";t.r(r);var a=t(56),n=Object(a.a)({},(function(){var e=this,r=e.$createElement,t=e._self._c||r;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"xml-支持-处理-xml-有效负载"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xml-支持-处理-xml-有效负载"}},[e._v("#")]),e._v(" XML 支持-处理 XML 有效负载")]),e._v(" "),t("h2",{attrs:{id:"xml-支持-处理-xml-有效负载-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xml-支持-处理-xml-有效负载-2"}},[e._v("#")]),e._v(" XML 支持-处理 XML 有效负载")]),e._v(" "),t("p",[e._v("Spring Integration 的 XML 支持扩展了 Spring Integration 与以下组件的核心:")]),e._v(" "),t("ul",[t("li",[t("p",[t("a",{attrs:{href:"#xml-transformation"}},[e._v("编组变压器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-transformation"}},[e._v("解组变压器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-transformation"}},[e._v("XSLT 变压器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-xpath-transformer"}},[e._v("XPath 转换器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-xpath-splitting"}},[e._v("XPath 拆分器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-xpath-routing"}},[e._v("XPath 路由器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-xpath-header-enricher"}},[e._v("XPath 报头 Enricher")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-xpath-filter"}},[e._v("XPath 过滤器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xpath-spel-function"}},[e._v("#XPath Spel 函数")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-validating-filter"}},[e._v("验证过滤器")])])])]),e._v(" "),t("p",[e._v("你需要在项目中包含此依赖项:")]),e._v(" "),t("p",[e._v("Maven")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("\n org.springframework.integration\n spring-integration-xml\n 5.5.9\n\n")])])]),t("p",[e._v("Gradle")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('compile "org.springframework.integration:spring-integration-xml:5.5.9"\n')])])]),t("p",[e._v("这些组件使得在 Spring 集成中处理 XML 消息变得更加简单。消息传递组件使用以一系列格式表示的 XML,包括"),t("code",[e._v("java.lang.String")]),e._v("、"),t("code",[e._v("org.w3c.dom.Document")]),e._v("和"),t("code",[e._v("javax.xml.transform.Source")]),e._v("的实例。但是,如果需要 DOM 表示(例如,为了计算 XPath 表达式),则将"),t("code",[e._v("String")]),e._v("有效负载转换为所需的类型,然后将其转换回"),t("code",[e._v("String")]),e._v("。需要"),t("code",[e._v("DocumentBuilder")]),e._v("实例的组件如果不提供名称空间感知实例,则创建该实例。当需要对文档创建进行更大的控制时,可以提供"),t("code",[e._v("DocumentBuilder")]),e._v("的适当配置实例。")]),e._v(" "),t("h3",{attrs:{id:"名称空间支持"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#名称空间支持"}},[e._v("#")]),e._v(" 名称空间支持")]),e._v(" "),t("p",[e._v("Spring 集成 XML 模块中的所有组件都提供了名称空间支持。为了启用名称空间支持,你需要为 Spring Integration XML 模块导入模式。下面的示例展示了一个典型的设置:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n\n')])])]),t("h4",{attrs:{id:"xpath-表达式"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xpath-表达式"}},[e._v("#")]),e._v(" XPath 表达式")]),e._v(" "),t("p",[e._v("Spring 集成 XML 模块中的许多组件都使用 XPath 表达式。这些组件中的每一个都引用了已定义为顶级元素的 XPath 表达式,或者使用了嵌套的"),t("code",[e._v("")]),e._v("元素。")]),e._v(" "),t("p",[e._v("所有形式的 XPath 表达式都会创建一个"),t("code",[e._v("XPathExpression")]),e._v(",该表达式使用 Spring "),t("code",[e._v("org.springframework.xml.xpath.XPathExpressionFactory")]),e._v("。在创建 XPath 表达式时,将使用 Classpath 上可用的最佳 XPath 实现(JAXP1.3+ 或 JAXen,其中首选 JAXP)。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("在内部, Spring 集成使用了 Spring Web 服务项目("),t("a",{attrs:{href:"https://www.spring.io/spring-ws",target:"_blank",rel:"noopener noreferrer"}},[e._v("https://www.spring.io/spring-ws"),t("OutboundLink")],1),e._v(")提供的 XPath 功能。"),t("br"),e._v("具体地说,我们使用 Spring Web 服务 XML 模块( Spring-xml-x.x.x.jar)。"),t("br"),e._v("有关更深入的理解,请参见"),t("a",{attrs:{href:"https://docs.spring.io/spring-ws/docs/current/reference/#xpath",target:"_blank",rel:"noopener noreferrer"}},[e._v("https://docs.spring.io/spring-ws/docs/current/reference/#xpath"),t("OutboundLink")],1),e._v("上的相应文档。")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("下面是"),t("code",[e._v("xpath-expression")]),e._v("元素的所有可用配置参数的概述:下面的清单显示了"),t("code",[e._v("xpath-expression")]),e._v("元素的可用属性:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v(' (5)\n (6)\n\n')])])]),t("table",[t("thead",[t("tr",[t("th",[t("strong",[e._v("1")])]),e._v(" "),t("th",[e._v("定义一个 XPath 表达式。"),t("br"),e._v("需要。")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[t("strong",[e._v("2")])]),e._v(" "),t("td",[e._v("底层 Bean 定义的标识符。"),t("br"),e._v("它是"),t("code",[e._v("org.springframework.xml.xpath.XPathExpression")]),e._v("的实例。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("3")])]),e._v(" "),t("td",[e._v("对包含名称空间的映射的引用。"),t("br"),e._v("映射的键定义了名称空间前缀,并且映射的值设置了名称空间 URI。"),t("br"),e._v("既指定这个属性又指定"),t("code",[e._v("map")]),e._v("元素或"),t("code",[e._v("ns-prefix")]),e._v("和"),t("code",[e._v("ns-uri")]),e._v("属性都是无效的。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("4")])]),e._v(" "),t("td",[e._v("让你直接将名称空间前缀设置为 XPath 表达式元素上的一个属性。"),t("br"),e._v("如果你设置"),t("code",[e._v("ns-prefix")]),e._v(",还必须设置"),t("code",[e._v("ns-uri")]),e._v("属性。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("5")])]),e._v(" "),t("td",[e._v("让你直接将名称空间 URI 设置为 XPath 表达式元素上的一个属性。"),t("br"),e._v("如果你设置"),t("code",[e._v("ns-uri")]),e._v(",还必须设置"),t("code",[e._v("ns-prefix")]),e._v("属性。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("6")])]),e._v(" "),t("td",[e._v("定义一个包含名称空间的映射。"),t("br"),e._v("只允许一个"),t("code",[e._v("map")]),e._v("子元素,"),t("br"),e._v("映射的键定义名称空间前缀,并且映射的值设置名称空间 URI。"),t("br"),e._v("既指定这个元素又指定"),t("code",[e._v("map")]),e._v("属性,或者设置"),t("code",[e._v("ns-prefix")]),e._v("和"),t("code",[e._v("ns-uri")]),e._v("属性都是无效的。"),t("br"),e._v("可选的。")])])])]),e._v(" "),t("h5",{attrs:{id:"为-xpath-表达式提供名称空间-可选"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#为-xpath-表达式提供名称空间-可选"}},[e._v("#")]),e._v(" 为 XPath 表达式提供名称空间(可选)")]),e._v(" "),t("p",[e._v("对于 XPath 表达式元素,你可以提供名称空间信息作为配置参数。你可以使用以下选项中的一个来定义名称空间:")]),e._v(" "),t("ul",[t("li",[t("p",[e._v("使用"),t("code",[e._v("namespace-map")]),e._v("属性引用地图")])]),e._v(" "),t("li",[t("p",[e._v("使用"),t("code",[e._v("map")]),e._v("子元素提供名称空间的映射")])]),e._v(" "),t("li",[t("p",[e._v("指定"),t("code",[e._v("ns-prefix")]),e._v("和"),t("code",[e._v("ns-uri")]),e._v("属性")])])]),e._v(" "),t("p",[e._v("这三种选择都是相互排斥的。只能设置一个选项。")]),e._v(" "),t("p",[e._v("下面的示例展示了使用 XPath 表达式的几种不同方式,包括设置 XML 名称空间"),t("a",{attrs:{href:"#xpath-namespace-support"}},[e._v("前面提到过")]),e._v("的选项:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n\n\n\n \n\n\n\n \n\n\n\n \n \n \n \n \n \n\n\n\n \n\n\n\n \n \n\n')])])]),t("h5",{attrs:{id:"使用带有默认名称空间的-xpath-表达式"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用带有默认名称空间的-xpath-表达式"}},[e._v("#")]),e._v(" 使用带有默认名称空间的 XPath 表达式")]),e._v(" "),t("p",[e._v("在使用默认名称空间时,你可能会遇到与预期的行为不同的情况。假设我们有以下 XML 文档(它代表两本书的顺序):")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n \n 0321200683\n 2\n \n \n 1590596439\n 1\n \n\n')])])]),t("p",[e._v("该文档不声明名称空间。因此,应用下面的 XPath 表达式如预期的那样工作:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("你可能认为相同的表达式也适用于以下 XML 文件:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n\t\n\t\t0321200683\n\t\t2\n\t\n\t\n\t\t1590596439\n\t\t1\n\t\n\n')])])]),t("p",[e._v("前面的示例看起来与前面的示例完全相同,但声明了一个默认的名称空间。")]),e._v(" "),t("p",[e._v("但是,前面的 XPath 表达式("),t("code",[e._v("/order/orderItem")]),e._v(")在这种情况下会失败。")]),e._v(" "),t("p",[e._v("为了解决这个问题,你必须通过设置"),t("code",[e._v("ns-prefix")]),e._v("和"),t("code",[e._v("ns-uri")]),e._v("属性或设置"),t("code",[e._v("namespace-map")]),e._v("属性来提供名称空间前缀和名称空间 URI。名称空间 URI 必须与 XML 文档中声明的名称空间匹配。在前面的示例中,这是"),t("code",[e._v("[http://www.example.org/orders](http://www.example.org/orders)")]),e._v("。")]),e._v(" "),t("p",[e._v("但是,你可以任意选择名称空间前缀。实际上,提供一个空字符串实际上是可行的。(但是,不允许使用 NULL)在名称空间前缀由空字符串组成的情况下,你的 XPath 表达式必须使用冒号(“:”)来指示默认的名称空间。如果不使用冒号,则 XPath 表达式不匹配。下面的 XPath 表达式与前面示例中的 XML 文档匹配:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("你还可以提供任何其他任意选择的名称空间前缀。下面的 XPath 表达式(使用"),t("code",[e._v("myorder")]),e._v("名称空间前缀)也匹配:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("名称空间 URI 是真正重要的信息,而不是前缀。这个 https://github.com/jaxen-xpath/jaxen[jaxen]很好地总结了这一点:")]),e._v(" "),t("blockquote",[t("p",[e._v("在 XPath1.0 中,所有无前缀的名称都是不合格的。\n不需要 XPath 表达式中使用的前缀与被查询的文档中使用的前缀相同。\n只有名称空间 URI 需要匹配,而不是前缀。")])]),e._v(" "),t("h3",{attrs:{id:"转换-xml-有效负载"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#转换-xml-有效负载"}},[e._v("#")]),e._v(" 转换 XML 有效负载")]),e._v(" "),t("p",[e._v("本节介绍了如何转换 XML 有效负载。")]),e._v(" "),t("h4",{attrs:{id:"将变压器配置为-bean"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#将变压器配置为-bean"}},[e._v("#")]),e._v(" 将变压器配置为 bean")]),e._v(" "),t("p",[e._v("本节将解释以下转换器的工作方式,以及如何将它们配置为 bean:")]),e._v(" "),t("ul",[t("li",[t("p",[t("a",{attrs:{href:"#xml-unmarshalling-transformer"}},[e._v("解组变压器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-marshalling-transformer"}},[e._v("编组变压器")])])]),e._v(" "),t("li",[t("p",[t("a",{attrs:{href:"#xml-xslt-payload-transformers"}},[e._v("XSLTpayloadTransformer")])])])]),e._v(" "),t("p",[e._v("所有的 XML 转换器都扩展了["),t("code",[e._v("AbstractTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/Transformer/AbstractTransformer.html)或["),t("code",[e._v("AbstractPayloadTransformer")]),e._v("(https://DOCS. Spring.io/ Spring-integration/api/org/org/integration/AbstractTransformer/AbstractTransformer/AbstractTransformer/AbstractTransformer/AbstractTransformer.html),并因此实现了[](https:////DOCS. Spring-integration/在 Spring 集成中将 XML 转换器配置为 bean 时,通常需要结合["),t("code",[e._v("Transformer")]),e._v('](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/Transforminghandler/MessageTransforminghandler.html)配置。这使得变压器可以用作端点。最后,我们讨论了名称空间支持,它允许将转换器配置为 XML 中的元素。')]),e._v(" "),t("h5",{attrs:{id:"解组变压器"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#解组变压器"}},[e._v("#")]),e._v(" 解组变压器")]),e._v(" "),t("p",[e._v("["),t("code",[e._v("UnmarshallingTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/transformer/unmarshallingtransformer.html)允许使用"),t("a",{attrs:{href:"https://docs.spring.io/spring/docs/current/spring-framework-reference/html/oxm.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring OXM"),t("OutboundLink")],1),t("code",[e._v("Unmarshaller")]),e._v("的实现来解组 XML"),t("code",[e._v("Source")]),e._v("。 Spring 的对象/XML 映射支持提供了几种实现,通过使用"),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/Java_Architecture_for_XML_Binding",target:"_blank",rel:"noopener noreferrer"}},[e._v("JAXB"),t("OutboundLink")],1),e._v("、"),t("a",{attrs:{href:"https://castor-data-binding.github.io/castor/reference-guide/reference/xml/xml-framework.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Castor"),t("OutboundLink")],1),e._v("、"),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/JiBX",target:"_blank",rel:"noopener noreferrer"}},[e._v("JiBX"),t("OutboundLink")],1),e._v("和其他方式支持编组和解组。解组器需要"),t("code",[e._v("Source")]),e._v("的实例。如果消息有效负载不是"),t("code",[e._v("Source")]),e._v("的实例,则仍将尝试转换。目前,"),t("code",[e._v("String")]),e._v("、"),t("code",[e._v("File")]),e._v("、"),t("code",[e._v("byte[]")]),e._v("和"),t("code",[e._v("org.w3c.dom.Document")]),e._v("都支持有效载荷。要创建到"),t("code",[e._v("Source")]),e._v("的自定义转换,可以注入一个["),t("code",[e._v("SourceFactory")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/source/sourcefactory.html)的实现。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("如果你没有显式地设置"),t("code",[e._v("SourceFactory")]),e._v(",则"),t("code",[e._v("UnmarshallingTransformer")]),e._v("上的属性默认设置为["),t("code",[e._v("DomSourceFactory")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/source/domsourceFactory.html)。")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("从版本 5.0 开始,"),t("code",[e._v("UnmarshallingTransformer")]),e._v("还支持将"),t("code",[e._v("org.springframework.ws.mime.MimeMessage")]),e._v("作为传入负载。当我们通过 SOAP 接收带有 MTOM 附件的 RAW"),t("code",[e._v("WebServiceMessage")]),e._v("时,这可能是有用的。有关更多信息,请参见"),t("RouterLink",{attrs:{to:"/spring-integration/ws.html#mtom-support"}},[e._v("MTOM 支持")]),e._v("。")],1),e._v(" "),t("p",[e._v("下面的示例展示了如何定义解组转换器:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n \n \n \n \n \n\n')])])]),t("h5",{attrs:{id:"使用marshallingtransformer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用marshallingtransformer"}},[e._v("#")]),e._v(" 使用"),t("code",[e._v("MarshallingTransformer")])]),e._v(" "),t("p",[e._v("["),t("code",[e._v("MarshallingTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/Transformer/MarshallingTransformer.html)允许通过使用 Spring OXM"),t("code",[e._v("Marshaller")]),e._v("将对象图转换为 XML。默认情况下,"),t("code",[e._v("MarshallingTransformer")]),e._v("返回"),t("code",[e._v("DomResult")]),e._v("。但是,你可以通过配置一个替代选项"),t("code",[e._v("ResultFactory")]),e._v("来控制结果的类型,例如"),t("code",[e._v("StringResultFactory")]),e._v("。在许多情况下,将有效负载转换为可选的 XML 格式更方便。为此,配置"),t("code",[e._v("ResultTransformer")]),e._v("。 Spring 集成提供了两种实现方式,一种转换为"),t("code",[e._v("String")]),e._v(",另一种转换为"),t("code",[e._v("Document")]),e._v("。下面的示例配置了一个可以转换为文档的编组转换器:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n \n \n \n \n \n \n \n \n\n')])])]),t("p",[e._v("默认情况下,"),t("code",[e._v("MarshallingTransformer")]),e._v("将有效负载对象传递给"),t("code",[e._v("Marshaller")]),e._v("。但是,如果将其布尔"),t("code",[e._v("extractPayload")]),e._v("属性设置为"),t("code",[e._v("false")]),e._v(",则整个"),t("code",[e._v("Message")]),e._v("实例将被传递给"),t("code",[e._v("Marshaller")]),e._v("。对于"),t("code",[e._v("Marshaller")]),e._v("接口的某些定制实现,这可能是有用的,但是,通常情况下,当你委托给各种"),t("code",[e._v("Marshaller")]),e._v("实现时,有效负载是用于编组的合适的源对象。")]),e._v(" "),t("h5",{attrs:{id:"xsltpayloadtransformer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xsltpayloadtransformer"}},[e._v("#")]),e._v(" xsltpayloadTransformer")]),e._v(" "),t("p",[e._v("["),t("code",[e._v("XsltPayloadTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/transformer/xsltpayloadTransformer.html)通过使用"),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/XSL_Transformations",target:"_blank",rel:"noopener noreferrer"}},[e._v("可扩展样式表语言转换"),t("OutboundLink")],1),e._v("转换 XML 有效负载。Transformer 的构造函数需要传入"),t("a",{attrs:{href:"https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/Resource.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Resource"),t("OutboundLink")],1),e._v("或"),t("a",{attrs:{href:"https://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Templates.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Templates"),t("OutboundLink")],1),e._v("的实例。传入"),t("code",[e._v("Templates")]),e._v("实例可以更好地配置用于创建模板实例的"),t("code",[e._v("TransformerFactory")]),e._v("实例。")]),e._v(" "),t("p",[e._v("与["),t("code",[e._v("UnmarshallingTransformer")]),e._v("](#xml-unmarshalling-transformer)一样,"),t("code",[e._v("XsltPayloadTransformer")]),e._v("针对"),t("code",[e._v("Source")]),e._v("的实例执行实际的 XSLT 转换。因此,如果消息有效负载不是"),t("code",[e._v("Source")]),e._v("的实例,则仍然尝试进行转换。"),t("code",[e._v("String")]),e._v("和"),t("code",[e._v("Document")]),e._v("有效负载是直接支持的。")]),e._v(" "),t("p",[e._v("要创建到"),t("code",[e._v("Source")]),e._v("的自定义转换,你可以注入一个["),t("code",[e._v("SourceFactory")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/source/sourcefactory.html)的实现。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("如果"),t("code",[e._v("SourceFactory")]),e._v("未显式设置,则"),t("code",[e._v("XsltPayloadTransformer")]),e._v("上的属性默认设置为["),t("code",[e._v("DomSourceFactory")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/source/domsourceFactory.html)。")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("默认情况下,"),t("code",[e._v("XsltPayloadTransformer")]),e._v("创建带有["),t("code",[e._v("Result")]),e._v("](https://DOCS.oracle.com/javase/6/DOCS/api/javax/xml/transform/result.html)有效负载的消息,类似于"),t("code",[e._v("XmlPayloadMarshallingTransformer")]),e._v("。你可以通过提供["),t("code",[e._v("ResultFactory")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/result/resultfactory.html)或["),t("code",[e._v("ResultTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/transformer/resultformer.html)来对此进行定制。")]),e._v(" "),t("p",[e._v("下面的示例配置 Bean 作为 XSLT 有效负载转换器工作的 Bean:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n \n \n \n \n\n')])])]),t("p",[e._v("从 Spring Integration3.0 开始,你可以通过使用构造函数参数来指定 Transformer Factory 类名。在使用名称空间时,可以使用"),t("code",[e._v("transformer-factory-class")]),e._v("属性来实现此目的。")]),e._v(" "),t("h5",{attrs:{id:"使用resulttransformer实现"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用resulttransformer实现"}},[e._v("#")]),e._v(" 使用"),t("code",[e._v("ResultTransformer")]),e._v("实现")]),e._v(" "),t("p",[t("code",[e._v("MarshallingTransformer")]),e._v("和"),t("code",[e._v("XsltPayloadTransformer")]),e._v("都允许你指定一个["),t("code",[e._v("ResultTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/Transformer/resultTransformer.html)。因此,如果编组或 XSLT 转换返回["),t("code",[e._v("Result")]),e._v("](https://DOCS.oracle.com/javase/6/DOCS/api/javax/xml/transform/result.html),则你还可以选择使用"),t("code",[e._v("ResultTransformer")]),e._v("将"),t("code",[e._v("Result")]),e._v("转换为另一种格式。 Spring 集成提供了两个具体的"),t("code",[e._v("ResultTransformer")]),e._v("实现:")]),e._v(" "),t("ul",[t("li",[t("p",[e._v("["),t("code",[e._v("ResultToDocumentTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/Transformer/ResultToDocumentTransformer.html)")])]),e._v(" "),t("li",[t("p",[e._v("["),t("code",[e._v("ResultToStringTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/Transformer/resultoStringTransformer.html)")])])]),e._v(" "),t("p",[e._v("默认情况下,"),t("code",[e._v("MarshallingTransformer")]),e._v("总是返回一个["),t("code",[e._v("Result")]),e._v("](https://DOCS.oracle.com/javase/6/DOCS/api/javax/xml/transform/result.html)。通过指定"),t("code",[e._v("ResultTransformer")]),e._v(",你可以自定义返回的有效负载的类型。")]),e._v(" "),t("p",[e._v("对于"),t("code",[e._v("XsltPayloadTransformer")]),e._v(",行为稍微复杂一些。默认情况下,如果输入有效负载是"),t("code",[e._v("String")]),e._v("或["),t("code",[e._v("Document")]),e._v("](https://DOCS.oracle.com/javase/6/DOCS/api/org/w3c/dom/document.html)的实例,则"),t("code",[e._v("resultTransformer")]),e._v("属性将被忽略。")]),e._v(" "),t("p",[e._v("但是,如果输入有效负载是["),t("code",[e._v("Source")]),e._v("](https://DOCS.oracle.com/javase/6/DOCS/api/javax/xml/transform/source.html)或任何其他类型,则应用"),t("code",[e._v("resultTransformer")]),e._v("属性。此外,你可以将"),t("code",[e._v("alwaysUseResultFactory")]),e._v("属性设置为"),t("code",[e._v("true")]),e._v(",这也会导致使用指定的"),t("code",[e._v("resultTransformer")]),e._v("。")]),e._v(" "),t("p",[e._v("有关更多信息和示例,请参见"),t("a",{attrs:{href:"#xml-using-result-transformers-namespace"}},[e._v("名称空间配置和结果转换器")]),e._v("。")]),e._v(" "),t("h4",{attrs:{id:"xml-transformers-的命名空间支持"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xml-transformers-的命名空间支持"}},[e._v("#")]),e._v(" XML Transformers 的命名空间支持")]),e._v(" "),t("p",[e._v("Spring Integration XML 命名空间提供了对所有 XML 转换器的命名空间支持,其模板为"),t("a",{attrs:{href:"#xpath-namespace-support"}},[e._v("显示在前面")]),e._v("。对 Transformers 的命名空间支持根据所提供的输入通道的类型创建"),t("code",[e._v("EventDrivenConsumer")]),e._v("或"),t("code",[e._v("PollingConsumer")]),e._v("的实例。名称空间支持旨在通过允许创建使用一个元素的端点和转换器来减少 XML 配置的数量。")]),e._v(" "),t("h5",{attrs:{id:"使用unmarshallingtransformer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用unmarshallingtransformer"}},[e._v("#")]),e._v(" 使用"),t("code",[e._v("UnmarshallingTransformer")])]),e._v(" "),t("p",[t("code",[e._v("UnmarshallingTransformer")]),e._v("的命名空间支持如下所示。由于名称空间创建的是一个端点实例,而不是一个转换器,因此你可以在元素中嵌入一个 poller 来控制输入通道的轮询。下面的示例展示了如何做到这一点:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n\n \n\n')])])]),t("h5",{attrs:{id:"使用marshallingtransformer-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用marshallingtransformer-2"}},[e._v("#")]),e._v(" 使用"),t("code",[e._v("MarshallingTransformer")])]),e._v(" "),t("p",[e._v("对编组转换器的命名空间支持需要"),t("code",[e._v("input-channel")]),e._v("、"),t("code",[e._v("output-channel")]),e._v("和对"),t("code",[e._v("marshaller")]),e._v("的引用。你可以使用可选的"),t("code",[e._v("result-type")]),e._v("属性来控制创建的结果类型。有效值为"),t("code",[e._v("StringResult")]),e._v("或"),t("code",[e._v("DomResult")]),e._v("(默认值)。下面的示例配置了一个编组转换器:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n\n\n\n')])])]),t("p",[e._v("如果提供的结果类型不够,则可以提供对"),t("code",[e._v("ResultFactory")]),e._v("的自定义实现的引用,作为使用"),t("code",[e._v("result-type")]),e._v("属性设置"),t("code",[e._v("result-type")]),e._v("属性的替代方法。"),t("code",[e._v("result-type")]),e._v("和"),t("code",[e._v("result-factory")]),e._v("属性是互斥的。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("在内部,"),t("code",[e._v("StringResult")]),e._v("和"),t("code",[e._v("DomResult")]),e._v("结果类型由"),t("code",[e._v("ResultFactory")]),e._v("实现表示:["),t("code",[e._v("StringResultFactory")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/result/stringresultfactory.html)和["),t("code",[e._v("DomResultFactory")]),e._v("(https://DOCS. Spring.io/ Spring-integration/api/api/integration/xml/result/resultfactory.html)。")])])]),e._v(" "),t("tbody")]),e._v(" "),t("h5",{attrs:{id:"使用xsltpayloadtransformer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用xsltpayloadtransformer"}},[e._v("#")]),e._v(" 使用"),t("code",[e._v("XsltPayloadTransformer")])]),e._v(" "),t("p",[e._v("对"),t("code",[e._v("XsltPayloadTransformer")]),e._v("的命名空间支持允许你传入"),t("code",[e._v("Resource")]),e._v("(以便创建["),t("code",[e._v("Templates")]),e._v("](https://DOCS.oracle.com/javase/6/DOCS/api/javax/xml/transform/templates.html)实例)或传入预先创建的"),t("code",[e._v("Templates")]),e._v("实例作为参考。与编组转换器一样,你可以通过指定"),t("code",[e._v("result-factory")]),e._v("或"),t("code",[e._v("result-type")]),e._v("属性来控制结果输出的类型。当需要在发送之前转换结果时,可以使用"),t("code",[e._v("result-transformer")]),e._v("属性来引用"),t("code",[e._v("ResultTransformer")]),e._v("的实现。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("如果指定"),t("code",[e._v("result-factory")]),e._v("或"),t("code",[e._v("result-type")]),e._v("属性,则底层["),t("code",[e._v("alwaysUseResultFactory")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/Transformer/xsltpayloadformer.html)上的"),t("code",[e._v("true")]),e._v("属性将被[<<"),t("code",[e._v("XsltPayloadTransformerParser")]),e._v("](https://DOCS. Spring.api/api/api/api/api/api/api63/apylotframFramework/xtframework/xparser.html)设置")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("下面的示例配置了两个 XSLT 转换器:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n\n')])])]),t("p",[e._v("你可能需要访问"),t("code",[e._v("Message")]),e._v("数据,例如"),t("code",[e._v("Message")]),e._v("头,以便协助转换。例如,你可能需要访问某些"),t("code",[e._v("Message")]),e._v("头,并将它们作为参数传递给转换器(例如,"),t("code",[e._v("transformer.setParameter(..)")]),e._v(")。 Spring 集成提供了两种方便的方式来实现这一点,如下例所示:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n \n \n\n')])])]),t("p",[e._v("如果消息头名称与参数名称一一匹配,则可以使用"),t("code",[e._v("xslt-param-headers")]),e._v("属性。在其中,你可以使用通配符进行简单的模式匹配。它支持以下简单的模式样式:"),t("code",[e._v("xxx*")]),e._v(","),t("code",[e._v("**xxx**")]),t("strong",[e._v(","),t("code",[e._v("*xxx")])]),e._v(",和"),t("code",[e._v("xxx*yyy")]),e._v("。")]),e._v(" "),t("p",[e._v("你还可以通过使用"),t("code",[e._v("")]),e._v("元素来配置各个 XSLT 参数。在该元素上,你可以设置"),t("code",[e._v("expression")]),e._v("属性或"),t("code",[e._v("value")]),e._v("属性。"),t("code",[e._v("expression")]),e._v("属性应该是任何有效的 SPEL 表达式,而"),t("code",[e._v("Message")]),e._v("是表达式求值上下文的根对象。"),t("code",[e._v("value")]),e._v("属性(与 Spring bean 中的任何"),t("code",[e._v("value")]),e._v("一样)允许你指定简单的标量值。你也可以使用属性占位符(例如"),t("code",[e._v("${some.value}")]),e._v(")。因此,使用"),t("code",[e._v("expression")]),e._v("和"),t("code",[e._v("value")]),e._v("属性,你可以将 XSLT 参数映射到"),t("code",[e._v("Message")]),e._v("的任何可访问部分以及任何文本值。")]),e._v(" "),t("p",[e._v("从 Spring Integration3.0 开始,你现在可以通过设置"),t("code",[e._v("transformer-factory-class")]),e._v("属性来指定 Transformer Factory 类名称。")]),e._v(" "),t("h4",{attrs:{id:"名称空间配置和结果转换器"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#名称空间配置和结果转换器"}},[e._v("#")]),e._v(" 名称空间配置和结果转换器")]),e._v(" "),t("p",[e._v("我们在[使用"),t("code",[e._v("ResultTransformer")]),e._v("实现](#xml-using-result-transformers)中介绍了使用结果转换器的情况。本节中的示例使用 XML 名称空间配置来演示几个特殊的用例。首先,我们定义"),t("code",[e._v("ResultTransformer")]),e._v(",如下例所示:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("此"),t("code",[e._v("ResultTransformer")]),e._v("接受"),t("code",[e._v("StringResult")]),e._v("或"),t("code",[e._v("DOMResult")]),e._v("作为输入,并将输入转换为"),t("code",[e._v("Document")]),e._v("。")]),e._v(" "),t("p",[e._v("现在我们可以申报变压器了,具体如下:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("如果传入消息的有效负载类型为"),t("code",[e._v("Source")]),e._v(",那么作为第一步,通过使用"),t("code",[e._v("ResultFactory")]),e._v("来确定"),t("code",[e._v("Result")]),e._v("。由于我们没有指定"),t("code",[e._v("ResultFactory")]),e._v(",所以使用了缺省的"),t("code",[e._v("DomResultFactory")]),e._v(",这意味着转换会产生"),t("code",[e._v("DomResult")]),e._v("。")]),e._v(" "),t("p",[e._v("然而,当我们指定一个"),t("code",[e._v("ResultTransformer")]),e._v("时,它被使用,结果"),t("code",[e._v("Message")]),e._v("的有效负载类型为"),t("code",[e._v("Document")]),e._v("。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("指定的"),t("code",[e._v("ResultTransformer")]),e._v("将被"),t("code",[e._v("String")]),e._v("或"),t("code",[e._v("Document")]),e._v("有效载荷忽略。"),t("br"),e._v("如果传入消息的有效载荷类型为"),t("code",[e._v("String")]),e._v(",则 XSLT 转换后的有效载荷为"),t("code",[e._v("String")]),e._v("。"),t("br"),e._v("类似地,如果传入消息的有效载荷类型为"),t("code",[e._v("Document")]),e._v(",XSLT 转换后的有效负载是"),t("code",[e._v("Document")]),e._v("。")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("如果消息有效负载不是"),t("code",[e._v("Source")]),e._v("、"),t("code",[e._v("String")]),e._v("或"),t("code",[e._v("Document")]),e._v(",则作为一个后备选项,我们尝试通过使用默认的["),t("code",[e._v("Source")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/source/sourcefactory.html)来创建"),t("code",[e._v("Source")]),e._v("。由于我们没有使用"),t("code",[e._v("source-factory")]),e._v("属性显式地指定"),t("code",[e._v("SourceFactory")]),e._v(",因此使用了默认的["),t("code",[e._v("DomSourceFactory")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/source/domsourcefactory.html)。如果成功,将执行 XSLT 转换,就好像负载类型"),t("code",[e._v("Source")]),e._v("一样,如前面几段所述。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[t("code",[e._v("DomSourceFactory")]),e._v("支持从"),t("code",[e._v("Document")]),e._v("、"),t("code",[e._v("File")]),e._v("或"),t("code",[e._v("String")]),e._v("有效负载创建"),t("code",[e._v("DOMSource")]),e._v("。")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("下一个 Transformer 声明添加了一个"),t("code",[e._v("result-type")]),e._v("属性,该属性使用"),t("code",[e._v("StringResult")]),e._v("作为其值。"),t("code",[e._v("result-type")]),e._v("在内部由"),t("code",[e._v("StringResultFactory")]),e._v("表示。因此,你还可以通过使用"),t("code",[e._v("result-factory")]),e._v("属性添加对"),t("code",[e._v("StringResultFactory")]),e._v("的引用,该属性本来是相同的。下面的示例展示了 Transformer 声明:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("因为我们使用了"),t("code",[e._v("ResultFactory")]),e._v(",所以"),t("code",[e._v("XsltPayloadTransformer")]),e._v("类的"),t("code",[e._v("alwaysUseResultFactory")]),e._v("属性隐式地设置为"),t("code",[e._v("true")]),e._v("。因此,使用了引用的"),t("code",[e._v("ResultToDocumentTransformer")]),e._v("。")]),e._v(" "),t("p",[e._v("因此,如果你转换类型为"),t("code",[e._v("String")]),e._v("的有效负载,则生成的有效负载类型为["),t("code",[e._v("Document")]),e._v("](https://DOCS.oracle.com/javase/6/DOCS/api/org/w3c/dom/document.html)。")]),e._v(" "),t("h5",{attrs:{id:"xsltpayloadtransformer和-xsl-output-method-text"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xsltpayloadtransformer和-xsl-output-method-text"}},[e._v("#")]),e._v(" "),t("code",[e._v("XsltPayloadTransformer")]),e._v("和"),t("code",[e._v('')])]),e._v(" "),t("p",[t("code",[e._v('')]),e._v("告诉 XSLT 模板仅从输入源生成文本内容。在这种特殊情况下,我们没有理由使用"),t("code",[e._v("DomResult")]),e._v("。因此,["),t("code",[e._v("XsltPayloadTransformer")]),e._v("](https://DOCS. Spring.io/ Spring-integration/api/org/springframework/integration/xml/transformer/xsltpayloadTransformer.html)默认为"),t("code",[e._v("StringResult")]),e._v("如果[输出属性](https://docs.oracle.com/javase/7/docs/api/javax/xml/transform/Transformer.html#getOutputProperties())调用底层"),t("code",[e._v("method")]),e._v("的"),t("code",[e._v("javax.xml.transform.Transformer")]),e._v("返回"),t("code",[e._v("text")]),e._v("。这种强制执行独立于入站有效负载类型。只有为"),t("code",[e._v("")]),e._v("组件设置 if"),t("code",[e._v("result-type")]),e._v("属性或"),t("code",[e._v("result-factory")]),e._v("属性时,此行为才可用。")]),e._v(" "),t("h3",{attrs:{id:"使用-xpath-转换-xml-消息"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用-xpath-转换-xml-消息"}},[e._v("#")]),e._v(" 使用 XPath 转换 XML 消息")]),e._v(" "),t("p",[e._v("当涉及到消息转换时,XPath 是转换具有 XML 有效负载的消息的一种很好的方法。你可以通过使用"),t("code",[e._v("")]),e._v("元素定义 XPath Transformers 来实现此目的。")]),e._v(" "),t("h4",{attrs:{id:"简单的-xpath-转换"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#简单的-xpath-转换"}},[e._v("#")]),e._v(" 简单的 XPath 转换")]),e._v(" "),t("p",[e._v("考虑以下变压器配置:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("还要考虑以下"),t("code",[e._v("Message")]),e._v(":")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Message message =\n MessageBuilder.withPayload(\"\").build();\n")])])]),t("p",[e._v("在将此消息发送到“InputChannel”之后,先前配置的 XPath Transformer 将此 XML 消息转换为一个简单的"),t("code",[e._v("Message")]),e._v(",其有效负载为’John Doe’,所有这些都基于"),t("code",[e._v("xpath-expression")]),e._v("属性中指定的简单 XPath 表达式。")]),e._v(" "),t("p",[e._v("XPath 还允许你将提取的元素简单地转换为所需的类型。有效的返回类型在"),t("code",[e._v("javax.xml.xpath.XPathConstants")]),e._v("中定义,并遵循"),t("code",[e._v("javax.xml.xpath.XPath")]),e._v("接口指定的转换规则。")]),e._v(" "),t("p",[e._v("下面的常量由"),t("code",[e._v("XPathConstants")]),e._v("类定义:"),t("code",[e._v("BOOLEAN")]),e._v(","),t("code",[e._v("DOM_OBJECT_MODEL")]),e._v(","),t("code",[e._v("NODE")]),e._v(","),t("code",[e._v("NODESET")]),e._v(","),t("code",[e._v("NUMBER")]),e._v(",和"),t("code",[e._v("STRING")]),e._v("。")]),e._v(" "),t("p",[e._v("可以通过使用"),t("code",[e._v("")]),e._v("元素的"),t("code",[e._v("evaluation-type")]),e._v("属性来配置所需的类型,如下例所示(两次):")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n\n')])])]),t("h4",{attrs:{id:"节点映射器"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#节点映射器"}},[e._v("#")]),e._v(" 节点映射器")]),e._v(" "),t("p",[e._v("如果需要为通过 XPath 表达式提取的节点提供自定义映射,则可以提供对"),t("code",[e._v("org.springframework.xml.xpath.NodeMapper")]),e._v("的实现的引用(由"),t("code",[e._v("XPathOperations")]),e._v("使用的接口实现为在每个节点的基础上映射"),t("code",[e._v("Node")]),e._v("对象)。要提供对"),t("code",[e._v("NodeMapper")]),e._v("的引用,可以使用"),t("code",[e._v("node-mapper")]),e._v("属性,如下例所示:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("下面的示例显示了与前面的示例一起工作的"),t("code",[e._v("NodeMapper")]),e._v("实现:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('class TestNodeMapper implements NodeMapper {\n public Object mapNode(Node node, int nodeNum) throws DOMException {\n return node.getTextContent() + "-mapped";\n }\n}\n')])])]),t("h4",{attrs:{id:"xml-有效载荷转换器"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xml-有效载荷转换器"}},[e._v("#")]),e._v(" XML 有效载荷转换器")]),e._v(" "),t("p",[e._v("你还可以使用"),t("code",[e._v("org.springframework.integration.xml.XmlPayloadConverter")]),e._v("的实现来提供更细粒度的转换。下面的示例展示了如何定义一个:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n')])])]),t("p",[e._v("下面的示例显示了与前面的示例一起工作的"),t("code",[e._v("XmlPayloadConverter")]),e._v("实现:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("class TestXmlPayloadConverter implements XmlPayloadConverter {\n public Source convertToSource(Object object) {\n throw new UnsupportedOperationException();\n }\n //\n public Node convertToNode(Object object) {\n try {\n return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(\n new InputSource(new StringReader(\"\")));\n }\n catch (Exception e) {\n throw new IllegalStateException(e);\n }\n }\n //\n public Document convertToDocument(Object object) {\n throw new UnsupportedOperationException();\n }\n}\n")])])]),t("p",[e._v("如果不提供此引用,则使用"),t("code",[e._v("DefaultXmlPayloadConverter")]),e._v("。在大多数情况下,它应该足够了,因为它可以从"),t("code",[e._v("Node")]),e._v("、"),t("code",[e._v("Document")]),e._v("、"),t("code",[e._v("Source")]),e._v("、"),t("code",[e._v("File")]),e._v("、"),t("code",[e._v("String")]),e._v("、"),t("code",[e._v("InputStream")]),e._v("和"),t("code",[e._v("byte[]")]),e._v("有效载荷转换。如果你需要扩展到该默认实现的功能之外,那么上游"),t("code",[e._v("Transformer")]),e._v("可能是一个更好的选择,而不是在这里提供对该策略的自定义实现的引用。")]),e._v(" "),t("h3",{attrs:{id:"分割-xml-消息"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#分割-xml-消息"}},[e._v("#")]),e._v(" 分割 XML 消息")]),e._v(" "),t("p",[t("code",[e._v("XPathMessageSplitter")]),e._v("支持带有"),t("code",[e._v("String")]),e._v("或"),t("code",[e._v("Document")]),e._v("有效负载的消息。拆分器使用提供的 XPath 表达式将有效负载拆分为多个节点。默认情况下,这将导致每个"),t("code",[e._v("Node")]),e._v("实例成为新消息的有效负载。当每条消息应该是"),t("code",[e._v("Document")]),e._v("时,可以设置"),t("code",[e._v("createDocuments")]),e._v("标志。在传入"),t("code",[e._v("String")]),e._v("有效载荷的情况下,将对有效载荷进行转换,然后将其拆分,然后再转换回许多"),t("code",[e._v("String")]),e._v("消息。XPath 拆分器实现"),t("code",[e._v("MessageHandler")]),e._v(",因此应该与适当的端点一起进行配置(请参阅下面示例之后的名称空间支持示例,以获得更简单的配置替代方案)。下面的示例配置使用"),t("code",[e._v("XPathMessageSplitter")]),e._v("的 Bean:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n \n \n \n \n \n \n \n \n\n')])])]),t("p",[e._v("XPath Splitter 名称空间支持允许你创建带有输入通道和输出通道的消息端点,如下例所示:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\x3c!-- Split the order into items and create a new message for each item node --\x3e\n\n \n\n\n\x3c!-- Split the order into items, create a new document for each item--\x3e\n\n \n \n\n')])])]),t("p",[e._v("从版本 4.2 开始,当请求"),t("code",[e._v("payload")]),e._v("类型不是"),t("code",[e._v("org.w3c.dom.Node")]),e._v("时,"),t("code",[e._v("outputProperties")]),e._v("实例的"),t("code",[e._v("OutputKeys.OMIT_XML_DECLARATION")]),e._v("属性(例如"),t("code",[e._v("OutputKeys.OMIT_XML_DECLARATION")]),e._v(")公开。下面的示例定义了一个属性,并将其与"),t("code",[e._v("output-properties")]),e._v("属性一起使用:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\tyes\n\n\n\n \n\n')])])]),t("p",[e._v("从"),t("code",[e._v("version 4.2")]),e._v("开始,"),t("code",[e._v("XPathMessageSplitter")]),e._v("将一个"),t("code",[e._v("iterator")]),e._v("选项公开为"),t("code",[e._v("boolean")]),e._v("标志(默认为"),t("code",[e._v("true")]),e._v(")。这允许下游流中分割节点的“流”。通过将"),t("code",[e._v("iterator")]),e._v("模式设置为"),t("code",[e._v("true")]),e._v(",每个节点在迭代时进行转换。当"),t("code",[e._v("false")]),e._v("时,首先对所有条目进行转换,然后将分割的节点开始发送到输出通道。(你可以将其视为“transform,send,transform,send,send”与“transform,transform,send,send”的区别。)有关更多信息,请参见"),t("RouterLink",{attrs:{to:"/spring-integration/splitter.html#splitter"}},[e._v("Splitter")]),e._v("。")],1),e._v(" "),t("h3",{attrs:{id:"使用-xpath-路由-xml-消息"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用-xpath-路由-xml-消息"}},[e._v("#")]),e._v(" 使用 XPath 路由 XML 消息")]),e._v(" "),t("p",[e._v("Spring 与基于 SPEL 的路由器类似,集成提供了对基于 XPath 表达式的路由消息的支持,它允许你创建具有输入通道但没有输出通道的消息端点。相反,一个或多个输出通道是动态确定的。下面的示例展示了如何创建这样的路由器:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n \n\n')])])]),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("有关路由器中常见的属性的概述,请参见"),t("RouterLink",{attrs:{to:"/spring-integration/router.html#router-common-parameters"}},[e._v("通用路由器参数")]),e._v("。")],1)])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("在内部,XPath 表达式被求值为类型"),t("code",[e._v("NODESET")]),e._v(",并转换为表示通道名的"),t("code",[e._v("List")]),e._v("。通常,这样的列表只包含一个通道名。然而,基于 XPath 表达式的结果,如果 XPath 表达式返回多个值,则 XPath 路由器还可以具有收件人列表路由器的特性。在这种情况下,"),t("code",[e._v("List")]),e._v("包含多个通道名。因此,消息被发送到列表中的所有通道。")]),e._v(" "),t("p",[e._v("因此,假设传递给以下路由器配置的 XML 文件包含许多表示通道名的"),t("code",[e._v("responder")]),e._v("子元素,则消息将被发送到所有这些通道:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\x3c!-- route the order to all responders--\x3e\n\n \n\n')])])]),t("p",[e._v("如果返回的值不直接表示通道名称,则可以指定其他映射参数,将这些返回的值映射到实际的通道名称。例如,如果"),t("code",[e._v("/request/responders")]),e._v("表达式导致两个值("),t("code",[e._v("responderA")]),e._v("和"),t("code",[e._v("responderB")]),e._v("),但不希望将响应者名称与通道名称耦合,则可以提供额外的映射配置,例如:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\x3c!-- route the order to all responders--\x3e\n\n \n \n \n\n')])])]),t("p",[e._v("如前所述,XPath 表达式的默认求值类型是"),t("code",[e._v("NODESET")]),e._v(",它被转换为通道名的"),t("code",[e._v("List")]),e._v(",它处理单个通道场景以及多个通道场景。")]),e._v(" "),t("p",[e._v("尽管如此,某些 XPath 表达式从一开始就可以计算为类型"),t("code",[e._v("String")]),e._v("。例如,考虑下面的 XPath 表达式:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("name(./node())\n")])])]),t("p",[e._v("这个表达式返回根节点的名称。如果使用了默认的求值类型"),t("code",[e._v("NODESET")]),e._v(",则会导致异常。")]),e._v(" "),t("p",[e._v("对于这些场景,你可以使用"),t("code",[e._v("evaluate-as-string")]),e._v("属性,该属性允许你管理求值类型。默认情况下是"),t("code",[e._v("FALSE")]),e._v("。但是,如果将其设置为"),t("code",[e._v("TRUE")]),e._v(",则使用"),t("code",[e._v("String")]),e._v("求值类型。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("XPath1.0 指定了 4 种数据类型:"),t("br"),t("br"),e._v("*node-sets"),t("br"),t("br"),e._v("*strings"),t("br"),e._v("*number"),t("br"),t("em",[e._v("boolean当使用可选路径"),t("br"),e._v("时,返回值由"),t("code",[e._v("string()")]),e._v("函数求值,正如 XPath 规范中所定义的。"),t("br"),e._v("这意味着,如果表达式选择了多个节点,它将返回第一个节点的字符串值。"),t("br"),t("br"),e._v("有关更多信息,请参见:"),t("br"),t("a",{attrs:{href:"https://www.w3.org/TR/xpath/",target:"_blank",rel:"noopener noreferrer"}},[e._v("规范:XMLPath 语言 1.0 版本"),t("OutboundLink")],1),t("br")]),t("a",{attrs:{href:"https://www.w3.org/TR/xpath-functions-31",target:"_blank",rel:"noopener noreferrer"}},[e._v("XPath 规范-string()函数"),t("OutboundLink")],1)])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("例如,如果我们想基于根节点的名称进行路由,我们可以使用以下配置:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n \n\n')])])]),t("h4",{attrs:{id:"xml-有效负载转换器"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xml-有效负载转换器"}},[e._v("#")]),e._v(" XML 有效负载转换器")]),e._v(" "),t("p",[e._v("对于 XPath 路由器,你还可以在 XPath 评估之前指定转换有效负载时使用的转换器。因此,XPath 路由器支持"),t("code",[e._v("XmlPayloadConverter")]),e._v("策略的自定义实现,并且当在 XML 中配置"),t("code",[e._v("xpath-router")]),e._v("元素时,可以通过"),t("code",[e._v("converter")]),e._v("属性提供对这种实现的引用。")]),e._v(" "),t("p",[e._v("如果没有显式提供此引用,则使用"),t("code",[e._v("DefaultXmlPayloadConverter")]),e._v("。在大多数情况下,它应该足够了,因为它可以从节点、文档、源、文件和字符串类型的有效负载转换。如果你需要扩展到该默认实现的能力之外,那么在大多数情况下,上游转换器通常是更好的选择,而不是在这里提供对此策略的自定义实现的引用。")]),e._v(" "),t("h3",{attrs:{id:"xpath-header-enricher"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xpath-header-enricher"}},[e._v("#")]),e._v(" XPath Header Enricher")]),e._v(" "),t("p",[e._v("XPath Header Enricher 定义了 Header Enricher 消息转换器,该消息转换器根据消息有效负载计算 XPath 表达式,并将计算结果插入到消息头中。")]),e._v(" "),t("p",[e._v("下面的清单显示了所有可用的配置参数:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v(' (5)\n (6)\n (12)\n\n')])])]),t("table",[t("thead",[t("tr",[t("th",[t("strong",[e._v("1")])]),e._v(" "),t("th",[e._v("指定是否覆盖现有标头值的默认布尔值。"),t("br"),e._v("这仅对不提供自己的“覆盖”属性的子元素有效,"),t("br"),e._v("如果不设置“默认-覆盖”属性,指定的标头值不会覆盖任何具有相同标头名的现有标头值。"),t("br"),e._v("可选。")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[t("strong",[e._v("2")])]),e._v(" "),t("td",[e._v("ID 为底层的 Bean 定义。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("3")])]),e._v(" "),t("td",[e._v("这个端点的接收消息通道。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("4")])]),e._v(" "),t("td",[e._v("丰富的消息被发送到的通道。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("5")])]),e._v(" "),t("td",[e._v("指定是否应跳过空值,例如可能从表达式求值返回的空值。"),t("br"),e._v("默认值是"),t("code",[e._v("true")]),e._v("。"),t("br"),e._v("如果空值应触发删除相应的标头,请将其设置为"),t("code",[e._v("false")]),e._v("。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("6")])]),e._v(" "),t("td",[e._v("与标题 Enricher 一起使用的 Poller。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("7")])]),e._v(" "),t("td",[e._v("要丰富的标题的名称。"),t("br"),e._v("强制。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("8")])]),e._v(" "),t("td",[e._v("如果你没有设置"),t("code",[e._v("header-type")]),e._v("属性,则这是该标头值的类型。"),t("br"),e._v("允许以下值:"),t("code",[e._v("BOOLEAN_RESULT")]),e._v(","),t("code",[e._v("STRING_RESULT")]),e._v(","),t("code",[e._v("NUMBER_RESULT")]),e._v(","),t("code",[e._v("NODE_RESULT")]),e._v(",以及"),t("code",[e._v("NODE_LIST_RESULT")]),e._v("。"),t("br"),e._v("如果未设置,它在内部默认为"),t("code",[e._v("XPathEvaluationType.STRING_RESULT")]),e._v("。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("9")])]),e._v(" "),t("td",[e._v("标头值类型的完全限定类名称。"),t("br"),e._v("XPath 求值的结果通过"),t("code",[e._v("ConversionService")]),e._v("转换为该类型。"),t("br"),e._v("例如,这允许,将"),t("code",[e._v("NUMBER_RESULT")]),e._v("(一个 double)转换为"),t("code",[e._v("Integer")]),e._v("。"),t("br"),e._v("该类型可以声明为原语(例如"),t("code",[e._v("int")]),e._v("),但结果总是等价的包装类(例如"),t("code",[e._v("Integer")]),e._v(")。"),t("br"),e._v("中讨论的相同的积分"),t("code",[e._v("ConversionService")]),e._v("用于转换,因此通过向服务中添加一个自定义转换器可以支持到自定义类型的转换。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("10")])]),e._v(" "),t("td",[e._v("布尔值,用于指示如果输入"),t("code",[e._v("Message")]),e._v("中已经存在,则此头标值是否应覆盖相同名称的现有头标值。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("11")])]),e._v(" "),t("td",[e._v("XPath 表达式为"),t("code",[e._v("String")]),e._v("。"),t("br"),e._v("必须设置这个属性或"),t("code",[e._v("xpath-expression-ref")]),e._v(",但不能同时设置这两个属性。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("12")])]),e._v(" "),t("td",[e._v("XPath 表达式引用."),t("br"),e._v("必须设置这个属性或"),t("code",[e._v("xpath-expression")]),e._v(",但不能同时设置这两个属性。")])])])]),e._v(" "),t("h3",{attrs:{id:"使用-xpath-过滤器"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用-xpath-过滤器"}},[e._v("#")]),e._v(" 使用 XPath 过滤器")]),e._v(" "),t("p",[e._v("这个组件定义了一个基于 XPath 的消息过滤器。在内部,这个组件使用"),t("code",[e._v("MessageFilter")]),e._v("来包装"),t("code",[e._v("AbstractXPathMessageSelector")]),e._v("的实例。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("有关更多详细信息,请参见"),t("RouterLink",{attrs:{to:"/spring-integration/filter.html#filter"}},[e._v("Filter")]),e._v("。")],1)])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("要使用 XPath 过滤器,你至少必须通过声明"),t("code",[e._v("xpath-expression")]),e._v("元素或在"),t("code",[e._v("xpath-expression-ref")]),e._v("属性中引用一个 XPath 表达式来提供一个 XPath 表达式。")]),e._v(" "),t("p",[e._v("如果提供的 XPath 表达式计算为"),t("code",[e._v("boolean")]),e._v("值,则不需要进一步的配置参数。但是,如果 XPath 表达式的求值为"),t("code",[e._v("String")]),e._v(",则应该设置"),t("code",[e._v("match-value")]),e._v("属性,并与求值结果进行匹配。")]),e._v(" "),t("p",[t("code",[e._v("match-type")]),e._v("有三种选择:")]),e._v(" "),t("ul",[t("li",[t("p",[t("code",[e._v("exact")]),e._v(":在"),t("code",[e._v("java.lang.String")]),e._v("上对应于"),t("code",[e._v("equals")]),e._v("。底层实现使用"),t("code",[e._v("StringValueTestXPathMessageSelector")])])]),e._v(" "),t("li",[t("p",[t("code",[e._v("case-insensitive")]),e._v(":在"),t("code",[e._v("java.lang.String")]),e._v("上对应于"),t("code",[e._v("equals-ignore-case")]),e._v("。底层实现使用"),t("code",[e._v("StringValueTestXPathMessageSelector")])])]),e._v(" "),t("li",[t("p",[t("code",[e._v("regex")]),e._v(":匹配操作 1"),t("code",[e._v("java.lang.String")]),e._v("。底层实现使用"),t("code",[e._v("RegexTestXPathMessageSelector")])])])]),e._v(" "),t("p",[e._v("当提供“regex”的“match-type”值时,带有"),t("code",[e._v("match-value")]),e._v("属性的值必须是有效的正则表达式。")]),e._v(" "),t("p",[e._v("下面的示例显示了"),t("code",[e._v("xpath-filter")]),e._v("元素的所有可用属性:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v(' (8)\n (9)\n (10)\n\n')])])]),t("table",[t("thead",[t("tr",[t("th",[t("strong",[e._v("1")])]),e._v(" "),t("th",[e._v("要发送被拒绝的消息的消息通道。"),t("br"),e._v("可选的。")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[t("strong",[e._v("2")])]),e._v(" "),t("td",[e._v("ID 为底层的 Bean 定义。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("3")])]),e._v(" "),t("td",[e._v("这个端点的接收消息通道。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("4")])]),e._v(" "),t("td",[e._v("要在 XPath 求值结果和"),t("code",[e._v("match-value")]),e._v("之间应用匹配的类型。"),t("br"),e._v("默认值是"),t("code",[e._v("exact")]),e._v("。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("5")])]),e._v(" "),t("td",[e._v("要与 XPath 求值结果匹配的字符串值。"),t("br"),e._v("如果不设置此属性,则 XPath 求值必须产生一个布尔结果。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("6")])]),e._v(" "),t("td",[e._v("将与筛选条件匹配的消息发送到的通道。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("7")])]),e._v(" "),t("td",[e._v("默认情况下,此属性被设置为"),t("code",[e._v("false")]),e._v(",并且被拒绝的消息(与筛选条件不匹配的消息)将被静默删除。"),t("br"),e._v("但是,如果设置为"),t("code",[e._v("true")]),e._v(",则消息拒绝将导致一个错误条件,并且异常将向上传播到调用者。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("8")])]),e._v(" "),t("td",[e._v("引用 XPath 表达式实例进行求值。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("9")])]),e._v(" "),t("td",[e._v("此子元素设置要求值的 XPath 表达式。"),t("br"),e._v("如果不包含此元素,则必须设置"),t("code",[e._v("xpath-expression-ref")]),e._v("属性。"),t("br"),e._v("此外,你只能包含一个"),t("code",[e._v("xpath-expression")]),e._v("元素。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("10")])]),e._v(" "),t("td",[e._v("与 XPath 过滤器一起使用的 Poller。"),t("br"),e._v("可选的。")])])])]),e._v(" "),t("h3",{attrs:{id:"xpath-spel-函数"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xpath-spel-函数"}},[e._v("#")]),e._v(" #XPath spel 函数")]),e._v(" "),t("p",[e._v("Spring 集成,自版本 3.0 以来,提供了内置的"),t("code",[e._v("#xpath")]),e._v("spel 函数,它调用"),t("code",[e._v("XPathUtils.evaluate(…​)")]),e._v("静态方法。此方法将委托给"),t("code",[e._v("org.springframework.xml.xpath.XPathExpression")]),e._v("。下面的清单展示了一些使用示例:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('\n\n\n\n\n\n\n \n \n\n')])])]),t("p",[t("code",[e._v("#xpath()")]),e._v("还支持用于转换 XPath 求值结果的第三个可选参数。它可以是字符串常量之一("),t("code",[e._v("string")]),e._v(","),t("code",[e._v("boolean")]),e._v(","),t("code",[e._v("number")]),e._v(","),t("code",[e._v("node")]),e._v(","),t("code",[e._v("node_list")]),e._v("和"),t("code",[e._v("document_list")]),e._v(")或"),t("code",[e._v("org.springframework.xml.xpath.NodeMapper")]),e._v("实例。默认情况下,"),t("code",[e._v("#xpath")]),e._v("spel 函数返回 XPath 求值的"),t("code",[e._v("String")]),e._v("表示。")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("要启用"),t("code",[e._v("#xpath")]),e._v("spel 函数,你可以将"),t("code",[e._v("spring-integration-xml.jar")]),e._v("添加到 Classpath。"),t("br"),e._v("你不需要从 Spring 集成 XML 命名空间中声明任何组件。")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("有关更多信息,请参见“`"),t("RouterLink",{attrs:{to:"/spring-integration/spel.html#spel"}},[e._v("Spring Expression Language (SpEL)")]),e._v("。")],1),e._v(" "),t("h3",{attrs:{id:"xml-验证过滤器"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#xml-验证过滤器"}},[e._v("#")]),e._v(" XML 验证过滤器")]),e._v(" "),t("p",[e._v("XML 验证过滤器允许你根据提供的模式实例验证传入消息。支持以下模式类型:")]),e._v(" "),t("ul",[t("li",[t("p",[e._v("xml-schema("),t("a",{attrs:{href:"https://www.w3.org/2001/XMLSchema",target:"_blank",rel:"noopener noreferrer"}},[e._v("https://www.w3.org/2001/XMLSchema"),t("OutboundLink")],1),e._v(")")])]),e._v(" "),t("li",[t("p",[e._v("relax-ng("),t("a",{attrs:{href:"https://relaxng.org",target:"_blank",rel:"noopener noreferrer"}},[e._v("https://relaxng.org"),t("OutboundLink")],1),e._v(")")])])]),e._v(" "),t("p",[e._v("验证失败的消息可以被静默删除,也可以转发到可定义的"),t("code",[e._v("discard-channel")]),e._v("。此外,你可以将此筛选器配置为在验证失败的情况下抛出"),t("code",[e._v("Exception")]),e._v("。")]),e._v(" "),t("p",[e._v("下面的清单显示了所有可用的配置参数:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v(' (9)\n (10)\n\n')])])]),t("table",[t("thead",[t("tr",[t("th",[t("strong",[e._v("1")])]),e._v(" "),t("th",[e._v("要发送被拒绝的消息的消息通道。"),t("br"),e._v("可选的。")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[t("strong",[e._v("2")])]),e._v(" "),t("td",[e._v("ID 为底层的 Bean 定义。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("3")])]),e._v(" "),t("td",[e._v("这个端点的接收消息通道。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("4")])]),e._v(" "),t("td",[e._v("要发送已接受的消息的消息通道。"),t("br"),e._v("可选的。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("5")])]),e._v(" "),t("td",[e._v("设置模式的位置以验证消息的有效负载。"),t("br"),e._v("内部使用"),t("code",[e._v("org.springframework.core.io.Resource")]),e._v("接口。"),t("br"),e._v("你可以设置此属性或"),t("code",[e._v("xml-validator")]),e._v("属性,但不能同时设置这两个属性。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("6")])]),e._v(" "),t("td",[e._v("设置模式类型。"),t("br"),e._v("可以是"),t("code",[e._v("xml-schema")]),e._v("或"),t("code",[e._v("relax-ng")]),e._v("。"),t("br"),e._v("可选的。"),t("br"),e._v("如果未设置,它默认为"),t("code",[e._v("xml-schema")]),e._v(",在内部翻译为"),t("code",[e._v("org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML")]),e._v("。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("7")])]),e._v(" "),t("td",[e._v("如果"),t("code",[e._v("true")]),e._v(",如果对所提供的消息的有效负载的验证失败,则抛出一个"),t("code",[e._v("MessageRejectedException")]),e._v("。"),t("br"),e._v("如果未设置,则默认为"),t("code",[e._v("false")]),e._v("。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("8")])]),e._v(" "),t("td",[e._v("参考自定义"),t("code",[e._v("org.springframework.integration.xml.XmlPayloadConverter")]),e._v("策略。"),t("br"),e._v("可选策略。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("9")])]),e._v(" "),t("td",[e._v("引用自定义的"),t("code",[e._v("sorg.springframework.xml.validation.XmlValidator")]),e._v("策略。"),t("br"),e._v("可以设置此属性或"),t("code",[e._v("schema-location")]),e._v("属性,但不能同时设置这两个属性。"),t("br"),e._v("可选。")])]),e._v(" "),t("tr",[t("td",[t("strong",[e._v("10")])]),e._v(" "),t("td",[e._v("与 XPath 过滤器一起使用的 Poller。"),t("br"),e._v("可选的。")])])])])])}),[],!1,null,null,null);r.default=n.exports}}]);