You need a transformer. Check below the modified method :
public static String removeNameSpace(String xml) {
try {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
transformer.setOutputProperty( OutputKeys.INDENT, "false" );
System.out.println("before xml = " + xml);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new StringReader(xml));
Document xmlDoc = builder.parse(inputSource);
Node root = xmlDoc.getDocumentElement();
NodeList rootchildren = root.getChildNodes();
Element newroot = xmlDoc.createElement(root.getNodeName());
for (int i = 0; i < rootchildren.getLength(); i++) {
newroot.appendChild(rootchildren.item(i).cloneNode(true));
}
xmlDoc.replaceChild(newroot, root);
DOMSource requestXMLSource = new DOMSource( xmlDoc.getDocumentElement() );
StringWriter requestXMLStringWriter = new StringWriter();
StreamResult requestXMLStreamResult = new StreamResult( requestXMLStringWriter );
transformer.transform( requestXMLSource, requestXMLStreamResult );
String modifiedRequestXML = requestXMLStringWriter.toString();
return modifiedRequestXML;
} catch (Exception e) {
System.out.println("Could not parse message as xml: " + e.getMessage());
}
return "";
}
Output :
before xml = <?xml version="1.0" encoding="UTF-8"?><Payment xmlns="http://api.com/schema/store/1.0"><Store>abc</Store></Payment>
afterNsRemoval = <?xml version="1.0" encoding="UTF-8"?><Payment><Store>abc</Store></Payment>
Answer from SomeDude on Stack OverflowYou need a transformer. Check below the modified method :
public static String removeNameSpace(String xml) {
try {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
transformer.setOutputProperty( OutputKeys.INDENT, "false" );
System.out.println("before xml = " + xml);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new StringReader(xml));
Document xmlDoc = builder.parse(inputSource);
Node root = xmlDoc.getDocumentElement();
NodeList rootchildren = root.getChildNodes();
Element newroot = xmlDoc.createElement(root.getNodeName());
for (int i = 0; i < rootchildren.getLength(); i++) {
newroot.appendChild(rootchildren.item(i).cloneNode(true));
}
xmlDoc.replaceChild(newroot, root);
DOMSource requestXMLSource = new DOMSource( xmlDoc.getDocumentElement() );
StringWriter requestXMLStringWriter = new StringWriter();
StreamResult requestXMLStreamResult = new StreamResult( requestXMLStringWriter );
transformer.transform( requestXMLSource, requestXMLStreamResult );
String modifiedRequestXML = requestXMLStringWriter.toString();
return modifiedRequestXML;
} catch (Exception e) {
System.out.println("Could not parse message as xml: " + e.getMessage());
}
return "";
}
Output :
before xml = <?xml version="1.0" encoding="UTF-8"?><Payment xmlns="http://api.com/schema/store/1.0"><Store>abc</Store></Payment>
afterNsRemoval = <?xml version="1.0" encoding="UTF-8"?><Payment><Store>abc</Store></Payment>
Consider XSLT as removing declared/undeclared namespace is a regular task. Here, no third-party modules are needed as base Java is equipped with an XSLT 1.0 processor. Additionally, no loops or XML tags/attribs re-creation is handled as XSLT takes care of the transformation.
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class XPathUtils {
public static void main(String[] args) {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Payment xmlns=\"http://api.com/schema/store/1.0\"><Store>abc</Store></Payment>";
String afterNsRemoval = removeNameSpace(xml);
System.out.println("afterNsRemoval = " + afterNsRemoval);
}
public static String removeNameSpace(String xml) {
try{
String xslStr = String.join("\n",
"<xsl:transform xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">",
"<xsl:output version=\"1.0\" encoding=\"UTF-8\" indent=\"no\"/>",
"<xsl:strip-space elements=\"*\"/>",
" <xsl:template match=\"@*|node()\">",
" <xsl:element name=\"{local-name()}\">",
" <xsl:apply-templates select=\"@*|node()\"/>",
" </xsl:element>",
" </xsl:template>",
" <xsl:template match=\"text()\">",
" <xsl:copy/>",
" </xsl:template>",
"</xsl:transform>");
// Parse XML and Build Document
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
Document doc = db.parse (is);
// Parse XSLT and Configure Transformer
Source xslt = new StreamSource(new StringReader(xslStr));
Transformer tf = TransformerFactory.newInstance().newTransformer(xslt);
// Output Result to String
DOMSource source = new DOMSource(doc);
StringWriter outWriter = new StringWriter();
StreamResult strresult = new StreamResult( outWriter );
tf.transform(source, strresult);
StringBuffer sb = outWriter.getBuffer();
String finalstring = sb.toString();
return(finalstring);
} catch (Exception e) {
System.out.println("Could not parse message as xml: " + e.getMessage());
}
return "";
}
}
You can use xslt for that. Try
removeNs.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Sample.java
import java.io.File;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class Sample {
public static void main(String[] args) {
try{
TransformerFactory factory = TransformerFactory.newInstance();
Source xslt = new StreamSource(new File("removeNs.xslt"));
Transformer transformer = factory.newTransformer(xslt);
Source text = new StreamSource(new File("data.xml"));
transformer.transform(text, new StreamResult(new File("output.xml")));
System.out.println("Done");
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
}
Regex can be used for more information refer this
public static string RemoveAllXmlNamespace(string xmlData)
{
string xmlnsPattern = "\\s+xmlns\\s*(:\\w)?\\s*=\\s*\\\"(?<url>[^\\\"]*)\\\"";
MatchCollection matchCol = Regex.Matches(xmlData, xmlnsPattern);
foreach (Match m in matchCol)
{
xmlData = xmlData.Replace(m.ToString(), "");
}
return xmlData;
}
}
You can find a similar example here
Regex can be painful. you can also use this api (dom) to get rid of all namespaces.refer this
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
...
/**
* Recursively renames the namespace of a node.
* @param node the starting node.
* @param namespace the new namespace. Supplying <tt>null</tt> removes the namespace.
*/
public static void renameNamespaceRecursive(Node node, String namespace) {
Document document = node.getOwnerDocument();
if (node.getNodeType() == Node.ELEMENT_NODE) {
document.renameNode(node, namespace, node.getNodeName());
}
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); ++i) {
renameNamespaceRecursive(list.item(i), namespace);
}
}
Use the Regex function. This will solve this issue:
public static String removeXmlStringNamespaceAndPreamble(String xmlString) {
return xmlString.replaceAll("(<\\?[^<]*\\?>)?", ""). /* remove preamble */
replaceAll("xmlns.*?(\"|\').*?(\"|\')", "") /* remove xmlns declaration */
.replaceAll("(<)(\\w+:)(.*?>)", "$1$3") /* remove opening tag prefix */
.replaceAll("(</)(\\w+:)(.*?>)", "$1$3"); /* remove closing tags prefix */
}
You can pre-process XML to remove all namespaces, if you absolutely must do so. I'd recommend against it, as removing namespaces from an XML document is in essence comparable to removing namespaces from a programming framework or library - you risk name clashes and lose the ability to differentiate between once-distinct elements. However, it's your funeral. ;-)
This XSLT transformation removes all namespaces from any XML document.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="node()|@*" />
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{local-name()}">
<xsl:apply-templates select="node()|@*" />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Apply it to your XML document. Java examples for doing such a thing should be plenty, even on this site. The resulting document will be exactly of the same structure and layout, just without namespaces.
I found a solution to my problem. Posting it here if somebody lands here searching for an answer. I took a different approach. I let the CXF create the SOAP message and then I used the CXF custom interceptor to make changes to the message elements.
Configuration XML:
<!-- CXF Bus Configuration -->
<cxf:bus name="clientBus">
<cxf:outInterceptors>
<bean class="com.xxx.xxx.xxx.xxx.CustomMessageInterceptor" />
</cxf:outInterceptors>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
CustomMessageInterceptor.java
package com.xxx.xxx.xxx.xxx;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class CustomMessageInterceptor extends AbstractPhaseInterceptor<Message> {
public CustomMessageInterceptor() {
super(Phase.PRE_STREAM);
addBefore(SoapPreProtocolOutInterceptor.class.getName());
}
private Logger log = LoggerFactory.getLogger(this.getClass());
public void handleMessage(
Message message) {
OutputStream os = message.getContent(OutputStream.class);
CachedStream cs = new CachedStream();
message.setContent(OutputStream.class, cs);
message.getInterceptorChain().doIntercept(message);
try {
cs.flush();
IOUtils.closeQuietly(cs);
CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class);
String currentEnvelopeMessage = IOUtils.toString(csnew.getInputStream(), "UTF-8");
csnew.flush();
IOUtils.closeQuietly(csnew);
if (log.isDebugEnabled()) {
log.debug("Outbound message: " + currentEnvelopeMessage);
}
String res = changeOutboundMessage(currentEnvelopeMessage);
if (res != null) {
if (log.isDebugEnabled()) {
log.debug("Outbound message has been changed: " + res);
}
}
res = res != null ? res : currentEnvelopeMessage;
InputStream replaceInStream = IOUtils.toInputStream(res, "UTF-8");
IOUtils.copy(replaceInStream, os);
replaceInStream.close();
IOUtils.closeQuietly(replaceInStream);
os.flush();
message.setContent(OutputStream.class, os);
IOUtils.closeQuietly(os);
}
catch (IOException ioe) {
log.error("Unable to perform change.", ioe);
throw new RuntimeException(ioe);
}
}
protected String changeOutboundMessage(
String currentEnvelope) {
currentEnvelope = currentEnvelope.replace("<ClruInsert xmlns=\"\" xmlns:ns22=\"http://services/businessdomain/distributionmanagement/maintenance/maintenancerequestsresponses\">", "<ClruInsert>");
currentEnvelope = currentEnvelope.replace("<BusinessTypeCd xmlns=\"\" xmlns:ns22=\"http://services/businessdomain/distributionmanagement/maintenance/maintenancerequestsresponses\"", "<BusinessTypeCd");
return currentEnvelope;
}
private class CachedStream extends CachedOutputStream {
public CachedStream() {
super();
}
}
}
It worked like a charm! :)
Change
Element businessTypeCode = document.createElement("BusinessTypeCd");
to
Element businessTypeCode = document.createElementNS(
"http://services/businessdomain/distributionmanagement/maintenance/maintenancerequestsresponses",
"BusinessTypeCd");
and see https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Document.html#createElementNS-java.lang.String-java.lang.String- for more details.