SWS-797 - XsdSchemaHandlerAdapter does not transform schema locations
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2005-2012 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.ws.transport.http;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
import org.springframework.xml.xpath.XPathExpression;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link WsdlDefinitionHandlerAdapter} and {@link XsdSchemaHandlerAdapter} that transforms
|
||||
* XSD and WSDL location attributes.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.1.2
|
||||
*/
|
||||
public abstract class LocationTransformerObjectSupport extends TransformerObjectSupport {
|
||||
|
||||
/** Logger available to subclasses. */
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* Transforms the locations of the given definition document using the given XPath expression.
|
||||
* @param xPathExpression the XPath expression
|
||||
* @param definitionDocument the definition document
|
||||
* @param request the request, used to determine the location to transform to
|
||||
*/
|
||||
protected void transformLocations(XPathExpression xPathExpression,
|
||||
Document definitionDocument,
|
||||
HttpServletRequest request) {
|
||||
Assert.notNull(xPathExpression, "'xPathExpression' must not be null");
|
||||
Assert.notNull(definitionDocument, "'definitionDocument' must not be null");
|
||||
Assert.notNull(request, "'request' must not be null");
|
||||
|
||||
List<Node> locationNodes = xPathExpression.evaluateAsNodeList(definitionDocument);
|
||||
for (Node locationNode : locationNodes) {
|
||||
if (locationNode instanceof Attr) {
|
||||
Attr location = (Attr) locationNode;
|
||||
if (StringUtils.hasLength(location.getValue())) {
|
||||
String newLocation = transformLocation(location.getValue(), request);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Transforming [" + location.getValue() + "] to [" + newLocation + "]");
|
||||
}
|
||||
location.setValue(newLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the given location string to reflect the given request. If the given location is a full url, the
|
||||
* scheme, server name, and port are changed. If it is a relative url, the scheme, server name, and port are
|
||||
* prepended. Can be overridden in subclasses to change this behavior.
|
||||
* <p/>
|
||||
* For instance, if the location attribute defined in the WSDL is {@code http://localhost:8080/context/services/myService},
|
||||
* and the request URI for the WSDL is {@code http://example.com:80/context/myService.wsdl}, the location
|
||||
* will be changed to {@code http://example.com:80/context/services/myService}.
|
||||
* <p/>
|
||||
* If the location attribute defined in the WSDL is {@code /services/myService}, and the request URI for the
|
||||
* WSDL is {@code http://example.com:8080/context/myService.wsdl}, the location will be changed to
|
||||
* {@code http://example.com:8080/context/services/myService}.
|
||||
* <p/>
|
||||
* This method is only called when the {@code transformLocations} property is true.
|
||||
*/
|
||||
protected String transformLocation(String location, HttpServletRequest request) {
|
||||
StringBuilder url = new StringBuilder(request.getScheme());
|
||||
url.append("://").append(request.getServerName()).append(':').append(request.getServerPort());
|
||||
if (location.startsWith("/")) {
|
||||
// a relative path, prepend the context path
|
||||
url.append(request.getContextPath()).append(location);
|
||||
return url.toString();
|
||||
}
|
||||
else {
|
||||
int idx = location.indexOf("://");
|
||||
if (idx != -1) {
|
||||
// a full url
|
||||
idx = location.indexOf('/', idx + 3);
|
||||
if (idx != -1) {
|
||||
String path = location.substring(idx);
|
||||
url.append(path);
|
||||
return url.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
// unknown location, return the original
|
||||
return location;
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.ws.transport.http;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -28,19 +27,13 @@ import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.ws.wsdl.WsdlDefinition;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
import org.springframework.xml.xpath.XPathExpression;
|
||||
import org.springframework.xml.xpath.XPathExpressionFactory;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Adapter to use the {@code WsdlDefinition} interface with the generic {@code DispatcherServlet}.
|
||||
@@ -73,7 +66,7 @@ import org.w3c.dom.Node;
|
||||
* @see #transformLocation(String,javax.servlet.http.HttpServletRequest)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class WsdlDefinitionHandlerAdapter extends TransformerObjectSupport implements HandlerAdapter, InitializingBean {
|
||||
public class WsdlDefinitionHandlerAdapter extends LocationTransformerObjectSupport implements HandlerAdapter, InitializingBean {
|
||||
|
||||
/** Default XPath expression used for extracting all {@code location} attributes from the WSDL definition. */
|
||||
public static final String DEFAULT_LOCATION_EXPRESSION = "//@location";
|
||||
@@ -83,8 +76,6 @@ public class WsdlDefinitionHandlerAdapter extends TransformerObjectSupport imple
|
||||
|
||||
private static final String CONTENT_TYPE = "text/xml";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(WsdlDefinitionHandlerAdapter.class);
|
||||
|
||||
private Map<String, String> expressionNamespaces = new HashMap<String, String>();
|
||||
|
||||
private String locationExpression = DEFAULT_LOCATION_EXPRESSION;
|
||||
@@ -192,7 +183,7 @@ public class WsdlDefinitionHandlerAdapter extends TransformerObjectSupport imple
|
||||
* @see #transformLocation(String,javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
protected void transformLocations(Document definitionDocument, HttpServletRequest request) throws Exception {
|
||||
transformLocationsInternal(locationXPathExpression, definitionDocument, request);
|
||||
transformLocations(locationXPathExpression, definitionDocument, request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,63 +198,7 @@ public class WsdlDefinitionHandlerAdapter extends TransformerObjectSupport imple
|
||||
* @see #transformLocation(String,javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
protected void transformSchemaLocations(Document definitionDocument, HttpServletRequest request) throws Exception {
|
||||
transformLocationsInternal(schemaLocationXPathExpression, definitionDocument, request);
|
||||
transformLocations(schemaLocationXPathExpression, definitionDocument, request);
|
||||
}
|
||||
|
||||
private void transformLocationsInternal(XPathExpression xPathExpression,
|
||||
Document definitionDocument,
|
||||
HttpServletRequest request) throws Exception {
|
||||
List<Node> locationNodes = xPathExpression.evaluateAsNodeList(definitionDocument);
|
||||
for (Node locationNode : locationNodes) {
|
||||
if (locationNode instanceof Attr) {
|
||||
Attr location = (Attr) locationNode;
|
||||
if (StringUtils.hasLength(location.getValue())) {
|
||||
String newLocation = transformLocation(location.getValue(), request);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Transforming [" + location.getValue() + "] to [" + newLocation + "]");
|
||||
}
|
||||
location.setValue(newLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the given location string to reflect the given request. If the given location is a full url, the
|
||||
* scheme, server name, and port are changed. If it is a relative url, the scheme, server name, and port are
|
||||
* prepended. Can be overridden in subclasses to change this behavior.
|
||||
* <p/>
|
||||
* For instance, if the location attribute defined in the WSDL is {@code http://localhost:8080/context/services/myService},
|
||||
* and the request URI for the WSDL is {@code http://example.com:80/context/myService.wsdl}, the location
|
||||
* will be changed to {@code http://example.com:80/context/services/myService}.
|
||||
* <p/>
|
||||
* If the location attribute defined in the WSDL is {@code /services/myService}, and the request URI for the
|
||||
* WSDL is {@code http://example.com:8080/context/myService.wsdl}, the location will be changed to
|
||||
* {@code http://example.com:8080/context/services/myService}.
|
||||
* <p/>
|
||||
* This method is only called when the {@code transformLocations} property is true.
|
||||
*/
|
||||
protected String transformLocation(String location, HttpServletRequest request) {
|
||||
StringBuilder url = new StringBuilder(request.getScheme());
|
||||
url.append("://").append(request.getServerName()).append(':').append(request.getServerPort());
|
||||
if (location.startsWith("/")) {
|
||||
// a relative path, prepend the context path
|
||||
url.append(request.getContextPath()).append(location);
|
||||
return url.toString();
|
||||
}
|
||||
else {
|
||||
int idx = location.indexOf("://");
|
||||
if (idx != -1) {
|
||||
// a full url
|
||||
idx = location.indexOf('/', idx + 3);
|
||||
if (idx != -1) {
|
||||
String path = location.substring(idx);
|
||||
url.append(path);
|
||||
return url.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
// unknown location, return the original
|
||||
return location;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
* Copyright 2005-2012 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
|
||||
* 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,
|
||||
@@ -16,17 +16,25 @@
|
||||
|
||||
package org.springframework.ws.transport.http;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
import org.springframework.xml.xpath.XPathExpression;
|
||||
import org.springframework.xml.xpath.XPathExpressionFactory;
|
||||
import org.springframework.xml.xsd.XsdSchema;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* Adapter to use the {@link XsdSchema} interface with the generic <code>DispatcherServlet</code>.
|
||||
* <p/>
|
||||
@@ -38,12 +46,39 @@ import org.springframework.xml.xsd.XsdSchema;
|
||||
* @see #getSchemaSource(XsdSchema)
|
||||
* @since 1.5.3
|
||||
*/
|
||||
public class XsdSchemaHandlerAdapter extends TransformerObjectSupport implements HandlerAdapter {
|
||||
public class XsdSchemaHandlerAdapter extends LocationTransformerObjectSupport
|
||||
implements HandlerAdapter, InitializingBean {
|
||||
|
||||
/**
|
||||
* Default XPath expression used for extracting all {@code schemaLocation} attributes from the WSDL definition.
|
||||
*/
|
||||
public static final String DEFAULT_SCHEMA_LOCATION_EXPRESSION = "//@schemaLocation";
|
||||
|
||||
private static final String CONTENT_TYPE = "text/xml";
|
||||
|
||||
public boolean supports(Object handler) {
|
||||
return handler instanceof XsdSchema;
|
||||
private Map<String, String> expressionNamespaces = new HashMap<String, String>();
|
||||
|
||||
private String schemaLocationExpression = DEFAULT_SCHEMA_LOCATION_EXPRESSION;
|
||||
|
||||
private XPathExpression schemaLocationXPathExpression;
|
||||
|
||||
private boolean transformSchemaLocations = false;
|
||||
|
||||
/**
|
||||
* Sets the XPath expression used for extracting the {@code schemaLocation} attributes from the WSDL 1.1 definition.
|
||||
* <p/>
|
||||
* Defaults to {@code DEFAULT_SCHEMA_LOCATION_EXPRESSION}.
|
||||
*/
|
||||
public void setSchemaLocationExpression(String schemaLocationExpression) {
|
||||
this.schemaLocationExpression = schemaLocationExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether relative address schema locations in the WSDL are to be transformed using the request URI of the
|
||||
* incoming {@code HttpServletRequest}. Defaults to {@code false}.
|
||||
*/
|
||||
public void setTransformSchemaLocations(boolean transformSchemaLocations) {
|
||||
this.transformSchemaLocations = transformSchemaLocations;
|
||||
}
|
||||
|
||||
public long getLastModified(HttpServletRequest request, Object handler) {
|
||||
@@ -54,9 +89,18 @@ public class XsdSchemaHandlerAdapter extends TransformerObjectSupport implements
|
||||
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
if (HttpTransportConstants.METHOD_GET.equals(request.getMethod())) {
|
||||
response.setContentType(CONTENT_TYPE);
|
||||
Transformer transformer = createTransformer();
|
||||
Source schemaSource = getSchemaSource((XsdSchema) handler);
|
||||
|
||||
if (transformSchemaLocations) {
|
||||
DOMResult domResult = new DOMResult();
|
||||
transformer.transform(schemaSource, domResult);
|
||||
Document schemaDocument = (Document) domResult.getNode();
|
||||
transformSchemaLocations(schemaDocument, request);
|
||||
schemaSource = new DOMSource(schemaDocument);
|
||||
}
|
||||
|
||||
response.setContentType(CONTENT_TYPE);
|
||||
StreamResult responseResult = new StreamResult(response.getOutputStream());
|
||||
transformer.transform(schemaSource, responseResult);
|
||||
}
|
||||
@@ -66,6 +110,15 @@ public class XsdSchemaHandlerAdapter extends TransformerObjectSupport implements
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean supports(Object handler) {
|
||||
return handler instanceof XsdSchema;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
schemaLocationXPathExpression =
|
||||
XPathExpressionFactory.createXPathExpression(schemaLocationExpression, expressionNamespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Source} of the given schema. Allows for post-processing and transformation of the schema in
|
||||
* sub-classes.
|
||||
@@ -80,4 +133,19 @@ public class XsdSchemaHandlerAdapter extends TransformerObjectSupport implements
|
||||
return schema.getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms all {@code schemaLocation} attributes to reflect the server name given {@code HttpServletRequest}.
|
||||
* Determines the suitable attributes by evaluating the defined XPath expression, and delegates to {@code
|
||||
* transformLocation} to do the transformation for all attributes that match.
|
||||
* <p/>
|
||||
* This method is only called when the {@code transformSchemaLocations} property is true.
|
||||
*
|
||||
* @see #setSchemaLocationExpression(String)
|
||||
* @see #transformLocation(String, javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
protected void transformSchemaLocations(Document definitionDocument, HttpServletRequest request) throws Exception {
|
||||
transformLocations(schemaLocationXPathExpression, definitionDocument, request);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
* Copyright 2005-2012 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
|
||||
* 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,
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
package org.springframework.ws.transport.http;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -25,11 +29,12 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.xml.xsd.SimpleXsdSchema;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class XsdSchemaHandlerAdapterTest {
|
||||
|
||||
@@ -42,21 +47,22 @@ public class XsdSchemaHandlerAdapterTest {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
adapter = new XsdSchemaHandlerAdapter();
|
||||
adapter.afterPropertiesSet();
|
||||
request = new MockHttpServletRequest();
|
||||
response = new MockHttpServletResponse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLastModified() throws Exception {
|
||||
public void getLastModified() throws Exception {
|
||||
Resource single = new ClassPathResource("single.xsd", getClass());
|
||||
SimpleXsdSchema schema = new SimpleXsdSchema(single);
|
||||
schema.afterPropertiesSet();
|
||||
long lastModified = single.getFile().lastModified();
|
||||
Assert.assertEquals("Invalid last modified", lastModified, adapter.getLastModified(null, schema));
|
||||
assertEquals("Invalid last modified", lastModified, adapter.getLastModified(null, schema));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleGet() throws Exception {
|
||||
public void handleGet() throws Exception {
|
||||
request.setMethod(HttpTransportConstants.METHOD_GET);
|
||||
Resource single = new ClassPathResource("single.xsd", getClass());
|
||||
SimpleXsdSchema schema = new SimpleXsdSchema(single);
|
||||
@@ -67,10 +73,40 @@ public class XsdSchemaHandlerAdapterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleNonGet() throws Exception {
|
||||
public void handleNonGet() throws Exception {
|
||||
request.setMethod(HttpTransportConstants.METHOD_POST);
|
||||
adapter.handle(request, response, null);
|
||||
Assert.assertEquals("METHOD_NOT_ALLOWED expected", HttpServletResponse.SC_METHOD_NOT_ALLOWED,
|
||||
response.getStatus());
|
||||
assertEquals("METHOD_NOT_ALLOWED expected", HttpServletResponse.SC_METHOD_NOT_ALLOWED, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleGetWithTransformLocation() throws Exception {
|
||||
adapter.setTransformSchemaLocations(true);
|
||||
|
||||
request.setMethod(HttpTransportConstants.METHOD_GET);
|
||||
request.setScheme("http");
|
||||
request.setServerName("example.com");
|
||||
request.setServerPort(80);
|
||||
request.setContextPath("/context");
|
||||
request.setServletPath("/service.xsd");
|
||||
request.setPathInfo(null);
|
||||
request.setRequestURI("/context/service.xsd");
|
||||
|
||||
Resource importing = new ClassPathResource("importing-input.xsd", getClass());
|
||||
SimpleXsdSchema schema = new SimpleXsdSchema(importing);
|
||||
schema.afterPropertiesSet();
|
||||
|
||||
adapter.handle(request, response, schema);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(response.getContentAsByteArray());
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
documentBuilderFactory.setNamespaceAware(true);
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document resultingDocument = documentBuilder.parse(inputStream);
|
||||
|
||||
documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document expectedDocument = documentBuilder.parse(getClass().getResourceAsStream("importing-expected.xsd"));
|
||||
assertXMLEqual("Invalid WSDL returned", expectedDocument, resultingDocument);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
attributeFormDefault="qualified"
|
||||
elementFormDefault="qualified" targetNamespace="http://www.springframework.org/spring-ws/samples/echo">
|
||||
<import namespace="http://www.springframework.org/spring-ws/samples/echo/imported"
|
||||
schemaLocation="http://example.com:80/echo/services/imported.xsd"/>
|
||||
</schema>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
attributeFormDefault="qualified"
|
||||
elementFormDefault="qualified" targetNamespace="http://www.springframework.org/spring-ws/samples/echo">
|
||||
<import namespace="http://www.springframework.org/spring-ws/samples/echo/imported"
|
||||
schemaLocation="http://localhost:8080/echo/services/imported.xsd"/>
|
||||
</schema>
|
||||
Reference in New Issue
Block a user