diff --git a/src/java/net/brutex/xservices/types/AttributeType.java b/src/java/net/brutex/xservices/types/AttributeType.java
new file mode 100644
index 0000000..c5ac273
--- /dev/null
+++ b/src/java/net/brutex/xservices/types/AttributeType.java
@@ -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;
+}
diff --git a/src/java/net/brutex/xservices/ws/XmlService.java b/src/java/net/brutex/xservices/ws/XmlService.java
index 8b47103..d198cfc 100644
--- a/src/java/net/brutex/xservices/ws/XmlService.java
+++ b/src/java/net/brutex/xservices/ws/XmlService.java
@@ -21,7 +21,9 @@ import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlElement;
+import net.brutex.xservices.types.AttributeType;
import net.brutex.xservices.types.NamespaceListType;
+import net.brutex.xservices.types.StringSplitType;
import net.brutex.xservices.types.ant.FileResource;
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.")
public abstract String insertNodes(
@WebParam(name="sourcexml") String source,
+ @WebParam(name="encoding") String encoding,
@WebParam(name="namespaceList") NamespaceListType paramNamespaceListType,
@WebParam(name="xpath") @XmlElement(required=true) String paramString1,
@WebParam(name="xmldata") String paramString2)
@@ -60,7 +63,8 @@ public abstract interface XmlService
@WebMethod(operationName="replaceNodes")
@WSDLDocumentation("Replaces matched XML nodes with an XML document given as string.")
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="xpath") @XmlElement(required=true) String paramString1,
@WebParam(name="xmldata") String paramString2)
@@ -79,5 +83,24 @@ public abstract interface XmlService
@WSDLDocumentation("Wraps a String into a CDATA element")
public abstract String wrapInCDATA(@WebParam(name="data") @XmlElement(required=true) String data)
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;
}
diff --git a/src/java/net/brutex/xservices/ws/impl/XmlServiceImpl.java b/src/java/net/brutex/xservices/ws/impl/XmlServiceImpl.java
index cc0b992..9e369b9 100644
--- a/src/java/net/brutex/xservices/ws/impl/XmlServiceImpl.java
+++ b/src/java/net/brutex/xservices/ws/impl/XmlServiceImpl.java
@@ -21,26 +21,37 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
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.List;
import java.util.StringTokenizer;
import javax.jws.WebService;
+import javax.xml.namespace.QName;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
+
+import net.brutex.xservices.types.AttributeType;
import net.brutex.xservices.types.NamespaceListType;
import net.brutex.xservices.types.NamespaceType;
+import net.brutex.xservices.types.StringSplitType;
import net.brutex.xservices.types.ant.FileResource;
import net.brutex.xservices.ws.XServicesFault;
import net.brutex.xservices.ws.XmlService;
import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMCloneOptions;
+import org.apache.axiom.om.OMComment;
import org.apache.axiom.om.OMContainer;
import org.apache.axiom.om.OMDocument;
import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNode;
+import org.apache.axiom.om.OMProcessingInstruction;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.xpath.AXIOMXPath;
@@ -72,13 +83,7 @@ public class XmlServiceImpl implements XmlService {
}
// Initialize XPath context
- SimpleNamespaceContext context = new SimpleNamespaceContext();
- for (NamespaceType ns : nsList.getNamespaces()) {
- context.addNamespace(ns.getPrefix(), ns.getUri().toString());
- this.logger.debug(Messages.getString("XmlService.0")
- + ns.getPrefix() + "=\"" + ns.getUri().toString()
- + "\"'");
- }
+ SimpleNamespaceContext context = createContext(nsList);
axp.setNamespaceContext(context);
axp.addNamespaces(fragdoc.getOMDocumentElement());
@@ -103,87 +108,51 @@ 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 {
- AXIOMXPath axp = new AXIOMXPath(xpath);
-
- InputStream is = res.getAntResource(null).getInputStream();
-
- 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("" + replace + ""))
+ AXIOMXPath axp = new AXIOMXPath(xpath);
+ InputStream is = res.getAntResource(null).getInputStream();
+ OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is).getDocument();
+ OMDocument fragdoc = null;
+ if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
+ fragdoc = OMXMLBuilderFactory.createOMBuilder(
+ new StringReader("" + xmlFragment + ""))
.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();
+ throw new XServicesFault("No xmldata to insert.");
}
+
+ // Initialize XPath context
+ SimpleNamespaceContext context = createContext(nsList);
+ axp.setNamespaceContext(context);
+ axp.addNamespaces(fragdoc.getOMDocumentElement());
+
+ 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 (IOException e) {
+ e.printStackTrace();
+ throw new XServicesFault(e);
}
- 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 {
+ public String replaceNodes(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());
+ InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
.getDocument();
OMDocument fragdoc = null;
@@ -196,13 +165,7 @@ public class XmlServiceImpl implements XmlService {
}
// Initialize XPath context
- SimpleNamespaceContext context = new SimpleNamespaceContext();
- for (NamespaceType ns : nsList.getNamespaces()) {
- context.addNamespace(ns.getPrefix(), ns.getUri().toString());
- this.logger.debug(Messages.getString("XmlService.0")
- + ns.getPrefix() + "=\"" + ns.getUri().toString()
- + "\"'");
- }
+ SimpleNamespaceContext context = createContext(nsList);
axp.setNamespaceContext(context);
axp.addNamespaces(fragdoc.getOMDocumentElement());
@@ -221,13 +184,16 @@ public class XmlServiceImpl implements XmlService {
} catch (XMLStreamException e) {
e.printStackTrace();
throw new XServicesFault(e);
+ } catch (UnsupportedEncodingException e) {
+ throw new XServicesFault(e);
}
}
- public String insertNodes(String source, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
+ 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());
+ InputStream is = new ByteArrayInputStream(source.getBytes(encoding));
OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
.getDocument();
OMDocument fragdoc = null;
@@ -240,13 +206,7 @@ public class XmlServiceImpl implements XmlService {
}
// Initialize XPath context
- SimpleNamespaceContext context = new SimpleNamespaceContext();
- for (NamespaceType ns : nsList.getNamespaces()) {
- context.addNamespace(ns.getPrefix(), ns.getUri().toString());
- this.logger.debug(Messages.getString("XmlService.0")
- + ns.getPrefix() + "=\"" + ns.getUri().toString()
- + "\"'");
- }
+ SimpleNamespaceContext context = createContext(nsList);
axp.setNamespaceContext(context);
axp.addNamespaces(fragdoc.getOMDocumentElement());
@@ -265,6 +225,8 @@ public class XmlServiceImpl implements XmlService {
} catch (XMLStreamException e) {
e.printStackTrace();
throw new XServicesFault(e);
+ } catch (UnsupportedEncodingException e) {
+ throw new XServicesFault(e);
}
}
@@ -280,6 +242,115 @@ public class XmlServiceImpl implements XmlService {
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 {
List> olist = null;
try {
@@ -405,4 +476,31 @@ public class XmlServiceImpl implements XmlService {
xmldocument.build();
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;
+ }
}