Transforming XML Messages with XPath

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

Simple XPath Transformation

考虑以下转换器配置:

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

还需要考虑以下 Message

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

将此消息发送到 'inputChannel' 后,先前配置的 XPath 转换器会将此 XML 消息转换为带有有效负载 'John Doe' 的简单 Message,所有这些都基于 xpath-expression 属性中指定的简单 XPath 表达式。

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"/>

Node Mappers

如果你需要为 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"/>

以下示例展示了与前面示例一起使用的 NodeMapper 实现:

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

XML Payload Converter

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

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

以下示例展示了与前面示例一起使用的 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();
  }
}

如果您不提供此引用,则使用 DefaultXmlPayloadConverter。在大多数情况下,它就足够了,因为它可以从 NodeDocumentSourceFileStringInputStream`和 `byte[] 有效负载进行转换。如果您需要超出该默认实现的功能,那么上游 Transformer 可能比在此处提供对该策略的自定义实现的引用更好的选择。