Improve XmlService

git-svn-id: https://brutex.net/svn/xservices/trunk@127 e7e49efb-446e-492e-b9ec-fcafc1997a86
xservices-jre5
Brian Rosenberger 2013-02-11 08:15:11 +00:00
parent 58c7d94197
commit a7bfde4686
3 changed files with 252 additions and 96 deletions

View File

@ -0,0 +1,35 @@
/*
* Copyright 2013 Brian Rosenberger (Brutex Network)
*
* 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 net.brutex.xservices.types;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import net.brutex.xservices.util.BrutexNamespaces;
/**
* @author Brian Rosenberger, bru(at)brutex.de
*
*/
@XmlType(namespace=BrutexNamespaces.WS_XSERVICES, name=AttributeType.XML_NAME)
public class AttributeType {
public final static String XML_NAME = "AttributeType";
@XmlElement(required=true, nillable=false)
public String name;
@XmlElement(nillable=true)
public String value;
}

View File

@ -21,7 +21,9 @@ import javax.jws.WebParam;
import javax.jws.WebService; import javax.jws.WebService;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import net.brutex.xservices.types.AttributeType;
import net.brutex.xservices.types.NamespaceListType; import net.brutex.xservices.types.NamespaceListType;
import net.brutex.xservices.types.StringSplitType;
import net.brutex.xservices.types.ant.FileResource; import net.brutex.xservices.types.ant.FileResource;
import org.apache.cxf.annotations.WSDLDocumentation; import org.apache.cxf.annotations.WSDLDocumentation;
@ -43,6 +45,7 @@ public abstract interface XmlService
@WSDLDocumentation("Insert an XML fragment into an XML document given as string.") @WSDLDocumentation("Insert an XML fragment into an XML document given as string.")
public abstract String insertNodes( public abstract String insertNodes(
@WebParam(name="sourcexml") String source, @WebParam(name="sourcexml") String source,
@WebParam(name="encoding") String encoding,
@WebParam(name="namespaceList") NamespaceListType paramNamespaceListType, @WebParam(name="namespaceList") NamespaceListType paramNamespaceListType,
@WebParam(name="xpath") @XmlElement(required=true) String paramString1, @WebParam(name="xpath") @XmlElement(required=true) String paramString1,
@WebParam(name="xmldata") String paramString2) @WebParam(name="xmldata") String paramString2)
@ -61,6 +64,7 @@ public abstract interface XmlService
@WSDLDocumentation("Replaces matched XML nodes with an XML document given as string.") @WSDLDocumentation("Replaces matched XML nodes with an XML document given as string.")
public abstract String replaceNodes( public abstract String replaceNodes(
@WebParam(name="sourcexml") String source, @WebParam(name="sourcexml") String source,
@WebParam(name="encoding") String encoding,
@WebParam(name="namespaceList") NamespaceListType paramNamespaceListType, @WebParam(name="namespaceList") NamespaceListType paramNamespaceListType,
@WebParam(name="xpath") @XmlElement(required=true) String paramString1, @WebParam(name="xpath") @XmlElement(required=true) String paramString1,
@WebParam(name="xmldata") String paramString2) @WebParam(name="xmldata") String paramString2)
@ -80,4 +84,23 @@ public abstract interface XmlService
public abstract String wrapInCDATA(@WebParam(name="data") @XmlElement(required=true) String data) public abstract String wrapInCDATA(@WebParam(name="data") @XmlElement(required=true) String data)
throws XServicesFault; throws XServicesFault;
@WebMethod(operationName="selectXPath")
@WSDLDocumentation("Select from xml document given as string using an XPath expression.")
public abstract StringSplitType selectXPath(
@WebParam(name="sourcexml") @XmlElement(required=true) String source,
@WebParam(name="encoding") String encoding,
@WebParam(name="namespaceList") NamespaceListType paramNamespaceListType,
@WebParam(name="xpath") @XmlElement(required=true) String paramString1)
throws XServicesFault;
@WebMethod(operationName="setAttribute")
@WSDLDocumentation("Set an attribute.")
public abstract String setAttribute(
@WebParam(name="sourcexml") @XmlElement(required=true) String source,
@WebParam(name="encoding") String encoding,
@WebParam(name="namespaceList") NamespaceListType paramNamespaceListType,
@WebParam(name="xpath") @XmlElement(required=true) String paramString1,
@WebParam(name="attribute") @XmlElement(nillable=false, required=true) AttributeType attr)
throws XServicesFault;
} }

View File

@ -21,26 +21,37 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import javax.jws.WebService; import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter; import javax.xml.stream.XMLStreamWriter;
import net.brutex.xservices.types.AttributeType;
import net.brutex.xservices.types.NamespaceListType; import net.brutex.xservices.types.NamespaceListType;
import net.brutex.xservices.types.NamespaceType; import net.brutex.xservices.types.NamespaceType;
import net.brutex.xservices.types.StringSplitType;
import net.brutex.xservices.types.ant.FileResource; import net.brutex.xservices.types.ant.FileResource;
import net.brutex.xservices.ws.XServicesFault; import net.brutex.xservices.ws.XServicesFault;
import net.brutex.xservices.ws.XmlService; import net.brutex.xservices.ws.XmlService;
import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMCloneOptions; import org.apache.axiom.om.OMCloneOptions;
import org.apache.axiom.om.OMComment;
import org.apache.axiom.om.OMContainer; import org.apache.axiom.om.OMContainer;
import org.apache.axiom.om.OMDocument; import org.apache.axiom.om.OMDocument;
import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNode; import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMProcessingInstruction;
import org.apache.axiom.om.OMText; import org.apache.axiom.om.OMText;
import org.apache.axiom.om.OMXMLBuilderFactory; import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.xpath.AXIOMXPath; import org.apache.axiom.om.xpath.AXIOMXPath;
@ -72,13 +83,7 @@ public class XmlServiceImpl implements XmlService {
} }
// Initialize XPath context // Initialize XPath context
SimpleNamespaceContext context = new SimpleNamespaceContext(); SimpleNamespaceContext context = createContext(nsList);
for (NamespaceType ns : nsList.getNamespaces()) {
context.addNamespace(ns.getPrefix(), ns.getUri().toString());
this.logger.debug(Messages.getString("XmlService.0")
+ ns.getPrefix() + "=\"" + ns.getUri().toString()
+ "\"'");
}
axp.setNamespaceContext(context); axp.setNamespaceContext(context);
axp.addNamespaces(fragdoc.getOMDocumentElement()); axp.addNamespaces(fragdoc.getOMDocumentElement());
@ -103,89 +108,11 @@ public class XmlServiceImpl implements XmlService {
} }
} }
public String replaceNodesFromFile(FileResource res, NamespaceListType nsList, String xpath, String replace) throws XServicesFault { public String replaceNodesFromFile(FileResource res, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
try { try {
AXIOMXPath axp = new AXIOMXPath(xpath); AXIOMXPath axp = new AXIOMXPath(xpath);
InputStream is = res.getAntResource(null).getInputStream(); InputStream is = res.getAntResource(null).getInputStream();
OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
XMLStreamReader reader = OMXMLBuilderFactory.createOMBuilder(is)
.getDocument().getXMLStreamReader(false);
StringWriter sw = new StringWriter();
OMAbstractFactory.getOMFactory();
while (reader.hasNext()) {
if (reader.getEventType() == 1) {
OMElement element = OMXMLBuilderFactory
.createStAXOMBuilder(reader).getDocumentElement();
element.build();
SimpleNamespaceContext context = new SimpleNamespaceContext();
for (NamespaceType ns : nsList.getNamespaces()) {
context.addNamespace(ns.getPrefix(), ns.getUri()
.toString());
this.logger.debug(Messages.getString(
"XmlService.adding_namespace",
new Object[] { ns.getPrefix(),
ns.getUri().toString() }));
}
axp.setNamespaceContext(context);
axp.addNamespaces(element);
OMDocument xfrag = OMXMLBuilderFactory.createOMBuilder(
new StringReader("<XS>" + replace + "</XS>"))
.getDocument();
xfrag.build();
List list = axp.selectNodes(element);
for (Iterator localIterator2 = list.iterator(); localIterator2
.hasNext();) {
Object o = localIterator2.next();
if (!(o instanceof OMNode))
throw new XServicesFault(
"You must match a node to be replaced, but you matched something differen (attribute, etc.");
OMNode node = (OMNode) o;
Iterator<?> children = xfrag.getOMDocumentElement()
.getChildren();
while (children.hasNext()) {
OMNode container = (OMNode) children.next();
node.insertSiblingAfter((OMNode) container
.clone(new OMCloneOptions()));
}
node.detach();
// node.insertSiblingAfter(AXIOMUtil.stringToOM(replace));
}
XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
element.serialize(writer);
sw.flush();
} else {
reader.next();
}
}
this.logger.trace(sw.getBuffer().toString());
return sw.getBuffer().toString();
} catch (JaxenException e) {
e.printStackTrace();
throw new XServicesFault(e);
} catch (IOException e) {
e.printStackTrace();
throw new XServicesFault(e);
} catch (XMLStreamException e) {
e.printStackTrace();
throw new XServicesFault(e);
}
}
public String replaceNodes(String source, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
try {
AXIOMXPath axp = new AXIOMXPath(xpath);
InputStream is = new ByteArrayInputStream(source.getBytes());
OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
.getDocument();
OMDocument fragdoc = null; OMDocument fragdoc = null;
if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) { if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
fragdoc = OMXMLBuilderFactory.createOMBuilder( fragdoc = OMXMLBuilderFactory.createOMBuilder(
@ -196,13 +123,7 @@ public class XmlServiceImpl implements XmlService {
} }
// Initialize XPath context // Initialize XPath context
SimpleNamespaceContext context = new SimpleNamespaceContext(); SimpleNamespaceContext context = createContext(nsList);
for (NamespaceType ns : nsList.getNamespaces()) {
context.addNamespace(ns.getPrefix(), ns.getUri().toString());
this.logger.debug(Messages.getString("XmlService.0")
+ ns.getPrefix() + "=\"" + ns.getUri().toString()
+ "\"'");
}
axp.setNamespaceContext(context); axp.setNamespaceContext(context);
axp.addNamespaces(fragdoc.getOMDocumentElement()); axp.addNamespaces(fragdoc.getOMDocumentElement());
@ -221,13 +142,17 @@ public class XmlServiceImpl implements XmlService {
} catch (XMLStreamException e) { } catch (XMLStreamException e) {
e.printStackTrace(); e.printStackTrace();
throw new XServicesFault(e); throw new XServicesFault(e);
} catch (IOException e) {
e.printStackTrace();
throw new XServicesFault(e);
} }
} }
public String insertNodes(String source, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault { public String replaceNodes(String source, String encoding, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
encoding = validateEncoding(encoding);
try { try {
AXIOMXPath axp = new AXIOMXPath(xpath); AXIOMXPath axp = new AXIOMXPath(xpath);
InputStream is = new ByteArrayInputStream(source.getBytes()); InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is) OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
.getDocument(); .getDocument();
OMDocument fragdoc = null; OMDocument fragdoc = null;
@ -240,13 +165,48 @@ public class XmlServiceImpl implements XmlService {
} }
// Initialize XPath context // Initialize XPath context
SimpleNamespaceContext context = new SimpleNamespaceContext(); SimpleNamespaceContext context = createContext(nsList);
for (NamespaceType ns : nsList.getNamespaces()) { axp.setNamespaceContext(context);
context.addNamespace(ns.getPrefix(), ns.getUri().toString()); axp.addNamespaces(fragdoc.getOMDocumentElement());
this.logger.debug(Messages.getString("XmlService.0")
+ ns.getPrefix() + "=\"" + ns.getUri().toString() OMDocument document = replaceNodes(sourcedoc, axp, fragdoc);
+ "\"'");
StringWriter sw = new StringWriter();
XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
document.serialize(writer);
this.logger.trace(sw.getBuffer().toString());
return sw.getBuffer().toString();
} catch (JaxenException e) {
e.printStackTrace();
throw new XServicesFault(e);
} catch (XMLStreamException e) {
e.printStackTrace();
throw new XServicesFault(e);
} catch (UnsupportedEncodingException e) {
throw new XServicesFault(e);
} }
}
public String insertNodes(String source, String encoding, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
encoding = validateEncoding(encoding);
try {
AXIOMXPath axp = new AXIOMXPath(xpath);
InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
.getDocument();
OMDocument fragdoc = null;
if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
fragdoc = OMXMLBuilderFactory.createOMBuilder(
new StringReader("<XS>" + xmlFragment + "</XS>"))
.getDocument();
} else {
throw new XServicesFault("No xmldata to insert.");
}
// Initialize XPath context
SimpleNamespaceContext context = createContext(nsList);
axp.setNamespaceContext(context); axp.setNamespaceContext(context);
axp.addNamespaces(fragdoc.getOMDocumentElement()); axp.addNamespaces(fragdoc.getOMDocumentElement());
@ -265,6 +225,8 @@ public class XmlServiceImpl implements XmlService {
} catch (XMLStreamException e) { } catch (XMLStreamException e) {
e.printStackTrace(); e.printStackTrace();
throw new XServicesFault(e); throw new XServicesFault(e);
} catch (UnsupportedEncodingException e) {
throw new XServicesFault(e);
} }
} }
@ -280,6 +242,115 @@ public class XmlServiceImpl implements XmlService {
result = "<![CDATA[" + result + "]]>"; result = "<![CDATA[" + result + "]]>";
return result; return result;
} }
public StringSplitType selectXPath(String source, String encoding, NamespaceListType nsList, String xpath) throws XServicesFault {
encoding = validateEncoding(encoding);
try {
StringSplitType rarray = new StringSplitType();
AXIOMXPath axp = new AXIOMXPath(xpath);
InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
// Initialize XPath context
SimpleNamespaceContext context = createContext(nsList);
axp.setNamespaceContext(context);
List results = axp.selectNodes(sourcedoc);
for(Object o : results) {
String text = null;
if(o instanceof OMNode) {
switch (((OMNode)o).getType()) {
case OMNode.TEXT_NODE:
text = ((OMText)o).getText();
break;
case OMNode.COMMENT_NODE:
text = ((OMComment)o).getValue();
break;
case OMNode.PI_NODE:
text = ((OMProcessingInstruction)o).getValue();
break;
default:
StringWriter sw = new StringWriter();
XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
((OMNode)o).serialize(writer);
writer.flush();
text = sw.toString();
}
} else if(o instanceof OMAttribute) {
text = ((OMAttribute)o).getAttributeValue();
} else {
text = String.valueOf(o);
}
rarray.addStringMatch(text);
}
return rarray;
} catch (JaxenException e) {
e.printStackTrace();
throw new XServicesFault(e);
} catch (XMLStreamException e) {
// TODO Auto-generated catch block
throw new XServicesFault(e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new XServicesFault(e);
}
}
public String setAttribute(String source, String encoding, NamespaceListType nsList, String xpath, AttributeType attr) throws XServicesFault {
encoding = validateEncoding(encoding);
try {
StringSplitType rarray = new StringSplitType();
AXIOMXPath axp = new AXIOMXPath(xpath);
InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
OMFactory fac = OMAbstractFactory.getOMFactory();
// Initialize XPath context
SimpleNamespaceContext context = createContext(nsList);
axp.setNamespaceContext(context);
List results = axp.selectNodes(sourcedoc);
for(Object o : results) {
String text = null;
if(o instanceof OMNode) {
switch (((OMNode)o).getType()) {
case OMNode.ELEMENT_NODE:
OMElement node = ((OMElement)o);
if(attr.value == null) {
node.removeAttribute( node.getAttribute(new QName(attr.name)));
} else {
node.addAttribute(attr.name, attr.value, node.getNamespace());
}
break;
default:
throw new XServicesFault("XPath expression did not match an element node.");
}
} else {
throw new XServicesFault("XPath expression did not match a node.");
}
}
StringWriter sw = new StringWriter();
XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
sourcedoc.serialize(writer);
writer.flush();
return sw.toString();
} catch (JaxenException e) {
e.printStackTrace();
throw new XServicesFault(e);
} catch (XMLStreamException e) {
// TODO Auto-generated catch block
throw new XServicesFault(e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new XServicesFault(e);
}
}
private OMDocument insertNodes(OMDocument xmldocument, AXIOMXPath axp,OMDocument xmlfragment) throws XServicesFault { private OMDocument insertNodes(OMDocument xmldocument, AXIOMXPath axp,OMDocument xmlfragment) throws XServicesFault {
List<?> olist = null; List<?> olist = null;
try { try {
@ -405,4 +476,31 @@ public class XmlServiceImpl implements XmlService {
xmldocument.build(); xmldocument.build();
return xmldocument; return xmldocument;
} }
private SimpleNamespaceContext createContext(NamespaceListType nsList) {
// Initialize XPath context
SimpleNamespaceContext context = new SimpleNamespaceContext();
if(nsList != null) {
for (NamespaceType ns : nsList.getNamespaces()) {
context.addNamespace(ns.getPrefix(), ns.getUri().toString());
this.logger.debug(Messages.getString("XmlService.0")
+ ns.getPrefix() + "=\"" + ns.getUri().toString()
+ "\"'");
}
} else {
logger.debug("No namespaces defined.");
}
return context;
}
private String validateEncoding(String encoding) throws XServicesFault {
if(encoding == null || encoding.equals("")) { encoding=Charset.defaultCharset().displayName(); }
try {
Charset.isSupported(encoding);
} catch (IllegalCharsetNameException e) {
throw new XServicesFault("Endcoding '"+encoding+"' is not supported by this JRE.");
}
logger.debug("Setting source xml string encoding to '"+encoding+"'");
return encoding;
}
} }