跳到主要内容

使用 XPath 转换 XML 消息

QWen Plus 中英对照 Transforming XML Messages with XPath

当涉及到消息转换时,XPath 是转换具有 XML 负载的消息的好方法。你可以通过使用 <xpath-transformer/> 元素定义 XPath 转换器来实现。

简单的 XPath 转换

考虑以下变压器配置:

<int-xml:xpath-transformer input-channel="inputChannel" output-channel="outputChannel"
xpath-expression="/person/@name" />
xml

也请考虑以下 Message

Message<?> message =
MessageBuilder.withPayload("<person name='John Doe' age='42' married='true'/>").build();
java

将此消息发送到 'inputChannel' 后,之前配置的 XPath 转换器会根据 xpath-expression 属性中指定的简单 XPath 表达式,将此 XML 消息转换为简单的 Message,其有效负载为 'John Doe'。

XPath 还允许你对提取的元素进行简单的类型转换。有效的返回类型在 javax.xml.xpath.XPathConstants 中定义,并遵循 javax.xml.xpath.XPath 接口指定的转换规则。

XPathConstants 类定义了以下常量:BOOLEANDOM_OBJECT_MODELNODENODESETNUMBERSTRING

你可以通过使用 <xpath-transformer/> 元素的 evaluation-type 属性来配置所需的类型,如下例所示(两次):

<int-xml:xpath-transformer input-channel="numberInput" xpath-expression="/person/@age"
evaluation-type="NUMBER_RESULT" output-channel="output"/>

<int-xml:xpath-transformer input-channel="booleanInput"
xpath-expression="/person/@married = 'true'"
evaluation-type="BOOLEAN_RESULT" output-channel="output"/>
xml

节点映射器

如果你需要为 XPath 表达式提取的节点提供自定义映射,你可以提供 org.springframework.xml.xpath.NodeMapper (由 XPathOperations 实现用于逐个节点映射 Node 对象的接口) 实现的引用。要提供对 NodeMapper 的引用,你可以使用 node-mapper 属性,如下例所示:

<int-xml:xpath-transformer input-channel="nodeMapperInput" xpath-expression="/person/@age"
node-mapper="testNodeMapper" output-channel="output"/>
xml

下面的示例展示了一个与前面示例配合使用的 NodeMapper 实现:

class TestNodeMapper implements NodeMapper {
public Object mapNode(Node node, int nodeNum) throws DOMException {
return node.getTextContent() + "-mapped";
}
}
java

XML 负载转换器

你也可以使用 org.springframework.integration.xml.XmlPayloadConverter 的一个实现来提供更细粒度的转换。以下示例展示了如何定义一个:

<int-xml:xpath-transformer input-channel="customConverterInput"
output-channel="output" xpath-expression="/test/@type"
converter="testXmlPayloadConverter" />
xml

以下示例展示了一个与前述示例配合使用的 XmlPayloadConverter 实现:

class TestXmlPayloadConverter implements XmlPayloadConverter {
public Source convertToSource(Object object) {
throw new UnsupportedOperationException();
}
//
public Node convertToNode(Object object) {
try {
return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
new InputSource(new StringReader("<test type='custom'/>")));
}
catch (Exception e) {
throw new IllegalStateException(e);
}
}
//
public Document convertToDocument(Object object) {
throw new UnsupportedOperationException();
}
}
java

如果你不提供此引用,则使用 DefaultXmlPayloadConverter。在大多数情况下这应该已经足够,因为它可以转换来自 NodeDocumentSourceFileStringInputStreambyte[] 的负载。如果你需要扩展该默认实现的功能,上游的 Transformer 可能是一个更好的选择,而不是在这里提供对此策略自定义实现的引用。