From 13100735e0bd821674885bbff0653332660f3af4 Mon Sep 17 00:00:00 2001 From: Jonas Partner Date: Wed, 1 Oct 2008 13:38:53 +0000 Subject: [PATCH] XPathExpression namespace support --- .../IntegrationXmlNamespaceHandler.java | 2 + .../xml/config/XPathExpressionParser.java | 114 ++++++++++++++++++ .../xml/config/spring-integration-xml-1.0.xsd | 23 ++++ .../config/XPathExpressionParserTests.java | 76 ++++++++++++ 4 files changed, 215 insertions(+) create mode 100644 org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XPathExpressionParser.java create mode 100644 org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XPathExpressionParserTests.java diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java index 0f4e19dc58..12b64c608f 100644 --- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java @@ -31,6 +31,8 @@ public class IntegrationXmlNamespaceHandler extends NamespaceHandlerSupport { registerBeanDefinitionParser("xslt-transformer", new XsltPayloadTransformerParser()); registerBeanDefinitionParser("xpath-router", new XPathRouterParser()); registerBeanDefinitionParser("xpath-selector", new XPathSelectorParser()); + registerBeanDefinitionParser("xpath-expression", new XPathExpressionParser()); + } } diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XPathExpressionParser.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XPathExpressionParser.java new file mode 100644 index 0000000000..f4393a529c --- /dev/null +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XPathExpressionParser.java @@ -0,0 +1,114 @@ +/* + * Copyright 2002-2007 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.config; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.xml.xpath.XPathExpressionFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * + * @author Jonas Partner + * + */ +public class XPathExpressionParser extends AbstractSingleBeanDefinitionParser { + + @Override + protected boolean shouldGenerateId() { + return false; + } + + @Override + protected boolean shouldGenerateIdAsFallback() { + return true; + } + + @SuppressWarnings("unchecked") + @Override + protected Class getBeanClass(Element element) { + return XPathExpressionFactory.class; + } + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + String strXpathExpression = element.getAttribute("xpath-expression"); + String strXpathExpressionPrefix = element.getAttribute("ns-prefix"); + String strXpathExpressionNamespace = element.getAttribute("ns-uri"); + String nameSpaceMapRef = element.getAttribute("namespace-map"); + + Assert.hasText(strXpathExpression, "xpath-expression attribute is required"); + + boolean prefixProvided = StringUtils.hasText(strXpathExpressionPrefix); + boolean namespaceProvided = StringUtils.hasText(strXpathExpressionNamespace); + boolean namespaceMapProvided = StringUtils.hasText(nameSpaceMapRef); + + if (prefixProvided || namespaceProvided) { + Assert.isTrue(prefixProvided && namespaceProvided, + "Both xpath-prefix and xpath-namespace must be specified if one is specified"); + Assert.isTrue(!namespaceMapProvided, "It is not valid to sepcify both xpath-namespace and namespace-map"); + } + + builder.setFactoryMethod("createXPathExpression"); + builder.addConstructorArgValue(strXpathExpression); + + if (prefixProvided) { + Map namespaceMap = new HashMap(); + namespaceMap.put(strXpathExpressionPrefix, strXpathExpressionNamespace); + builder.addConstructorArgValue(namespaceMap); + } + else if (StringUtils.hasText(nameSpaceMapRef)) { + builder.addConstructorArgReference(nameSpaceMapRef); + } + else if (element.getChildNodes().getLength() > 0) { + NodeList nodeList = element.getChildNodes(); + Element mapElement = null; + int elementCount = 0; + for (int i = 0; i < nodeList.getLength(); i++) { + Node currentNode = nodeList.item(i); + if (currentNode.getNodeType() == Node.ELEMENT_NODE) { + mapElement = (Element) currentNode; + elementCount++; + } + } + Assert.isTrue(elementCount == 1, "Only one namespace map child allowed"); + if (mapElement != null) { + Map namespaceMap = parseNamespaceMapElement(mapElement, parserContext, builder.getBeanDefinition()); + builder.getBeanDefinition().getConstructorArgumentValues().addGenericArgumentValue(namespaceMap); + } + } + + } + + + + protected Map parseNamespaceMapElement(Element element, ParserContext parserContext, BeanDefinition parentDefinition) { + BeanDefinitionParserDelegate beanParser = new BeanDefinitionParserDelegate(parserContext.getReaderContext()); + beanParser.initDefaults(element.getOwnerDocument().getDocumentElement()); + return beanParser.parseMapElement(element, parentDefinition); + } + +} diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd index d3f4832996..b156946b52 100644 --- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd @@ -143,6 +143,29 @@ + + + + + Defines an XPath expression. + + + + + + + + + + + + + + outputOne"))); + } + + @Test + public void testNamespacedStringExpression() throws Exception { + String xmlDoc = ""; + XPathExpression xPathExpression = getXPathExpression(xmlDoc); + assertEquals("outputOne",xPathExpression.evaluateAsString(XmlTestUtil.getDocumentForString("outputOne"))); + assertEquals("",xPathExpression.evaluateAsString(XmlTestUtil.getDocumentForString("outputOne"))); + } + + @Test + public void testStringExpressionWithNamespaceMapReference() throws Exception { + StringBuffer xmlDoc = new StringBuffer(""); + xmlDoc.append(""); + XPathExpression xPathExpression = getXPathExpression(xmlDoc.toString()); + assertEquals("outputOne",xPathExpression.evaluateAsString(XmlTestUtil.getDocumentForString("outputOne"))); + assertEquals("",xPathExpression.evaluateAsString(XmlTestUtil.getDocumentForString("outputOne"))); + } + + @Test + public void testStringExpressionWithNamespaceInnerBean() throws Exception { + StringBuffer xmlDoc = new StringBuffer(""); + xmlDoc.append("").append(""); + XPathExpression xPathExpression = getXPathExpression(xmlDoc.toString()); + assertEquals("outputOne",xPathExpression.evaluateAsString(XmlTestUtil.getDocumentForString("outputOne"))); + assertEquals("",xPathExpression.evaluateAsString(XmlTestUtil.getDocumentForString("outputOne"))); + } + + + @Test(expected=BeanDefinitionStoreException.class) + public void testNamespacePrefixButNoUri() throws Exception { + String xmlDoc = ""; + XPathExpression xPathExpression = getXPathExpression(xmlDoc); + assertEquals("outputOne",xPathExpression.evaluateAsString(XmlTestUtil.getDocumentForString("outputOne"))); + assertEquals("",xPathExpression.evaluateAsString(XmlTestUtil.getDocumentForString("outputOne"))); + + } + + public XPathExpression getXPathExpression(String contextXml){ + TestXmlApplicationContext ctx = TestXmlApplicationContextHelper.getTestAppContext(contextXml); + return (XPathExpression) ctx.getBean("xpathExpression"); + } + + +}