/* * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.integration.xml.transformer; import org.w3c.dom.Node; import org.springframework.integration.transformer.AbstractTransformer; import org.springframework.integration.xml.DefaultXmlPayloadConverter; import org.springframework.integration.xml.XmlPayloadConverter; import org.springframework.integration.xml.xpath.XPathEvaluationType; import org.springframework.messaging.Message; import org.springframework.util.Assert; import org.springframework.xml.xpath.NodeMapper; import org.springframework.xml.xpath.XPathExpression; import org.springframework.xml.xpath.XPathExpressionFactory; /** * Transformer implementation that evaluates an XPath expression against the inbound * Message payload and returns a Message whose payload is the result of that evaluation. * Prior to evaluation, the payload may be converted by the configured {@link XmlPayloadConverter} * instance. The default converter type is {@link DefaultXmlPayloadConverter}. * <p> * The evaluation result type will depend on either the enumeration value provided to * {@link #setEvaluationType(XPathEvaluationType)} or the presence of a {@link NodeMapper}, * which takes precedence. If no {@link NodeMapper} or evaluation type is configured explicitly, * the default evaluation type is {@link XPathEvaluationType#STRING_RESULT}. * * @author Mark Fisher * @since 2.0 */ public class XPathTransformer extends AbstractTransformer { private final XPathExpression xpathExpression; private volatile XmlPayloadConverter converter = new DefaultXmlPayloadConverter(); private volatile XPathEvaluationType evaluationType = XPathEvaluationType.STRING_RESULT; private volatile NodeMapper<?> nodeMapper; /** * Create an {@link XPathTransformer} that will create an XPath expression from the given String * to be evaluated against converted inbound Message payloads. * * @param expression The expression. */ public XPathTransformer(String expression) { this.xpathExpression = XPathExpressionFactory.createXPathExpression(expression); } /** * Create an {@link XPathTransformer} that will evaluate the given {@link XPathExpression} * against converted inbound Message payloads. * * @param expression The expression. */ public XPathTransformer(XPathExpression expression) { Assert.notNull(expression, "expression must not be null"); this.xpathExpression = expression; } /** * Specify the expected {@link XPathEvaluationType}. The default is {@link XPathEvaluationType#STRING_RESULT}. * * @param evaluationType The evaluation type. */ public void setEvaluationType(XPathEvaluationType evaluationType) { Assert.notNull(evaluationType, "evaluationType must not be null."); this.evaluationType = evaluationType; } /** * Set a {@link NodeMapper} to use for generating the result object. By default the NodeMapper is null, * but if explicitly set, type determination is the responsibility of the NodeMapper, taking precedence * over any configured evaluationType. * * @param nodeMapper The node mapper. */ public void setNodeMapper(NodeMapper<?> nodeMapper) { this.nodeMapper = nodeMapper; } /** * Specify the {@link XmlPayloadConverter} to use when converting a Message payload prior to XPath evaluation. * * @param converter The payload converter. */ public void setConverter(XmlPayloadConverter converter) { Assert.notNull(converter, "converter must not be null"); this.converter = converter; } @Override public String getComponentType() { return "xml:xpath-transformer"; } @Override protected Object doTransform(Message<?> message) throws Exception { Node node = this.converter.convertToNode(message.getPayload()); Object result = null; if (this.nodeMapper != null) { result = this.xpathExpression.evaluateAsObject(node, this.nodeMapper); } else { result = this.evaluationType.evaluateXPath(this.xpathExpression, node); } return result; } }