com.crabshue.commons.xml.namespace.XmlNamespaceUtils Maven / Gradle / Ivy
package com.crabshue.commons.xml.namespace;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import com.crabshue.commons.exceptions.SystemException;
import com.crabshue.commons.xml.XmlDocumentBuilder;
import com.crabshue.commons.xml.exceptions.XmlErrorType;
import com.crabshue.commons.xml.inputsource.InputSourceBuilder;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
/**
* Utility class for XML namespaces operations.
*
*/
@Slf4j
public class XmlNamespaceUtils {
/**
* Extract the namespaces defined in an XML file.
*
* @param xmlFile the XML file.
* @return the map of prefixes/namespaces.
* @see #extractNamespaces(InputSource)
*/
public static Map extractNamespaces(@NonNull final File xmlFile) {
return extractNamespaces(InputSourceBuilder.newInputSource(xmlFile));
}
/**
* Extract the namespaces defined in an XML document.
*
* @param inputSource the XML document (as an {@link InputSource}).
* @return the map of prefixes/namespaces.
*/
public static Map extractNamespaces(@NonNull final InputSource inputSource) {
final Map ret = new HashMap<>();
try (InputStream is = inputSource.getByteStream()) {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
XMLStreamReader reader = inputFactory.createXMLStreamReader(is, StandardCharsets.UTF_8.displayName());
while (reader.hasNext()) {
int evt = reader.next();
if (evt == XMLStreamConstants.START_ELEMENT) {
QName qName = reader.getName();
if (qName != null) {
ret.put(qName.getPrefix(), qName.getNamespaceURI());
}
}
}
ret.put("xsi", "http://www.w3.org/2001/XMLSchema-instance");
} catch (XMLStreamException | IOException e) {
throw new SystemException(XmlErrorType.ERROR_PARSING_XML, e);
}
return ret;
}
/**
* Stringify a map of prefixes and namespace URIs.
*
* @param namespaces the map of prefixes and namespace URIs.
* @return the stringified version of the map.
*/
public static String stringify(@NonNull final Map namespaces) {
StringBuilder sb = new StringBuilder();
sb.append(" ");
for (Map.Entry entry : namespaces.entrySet()) {
if (StringUtils.isNotBlank(entry.getKey())) {
sb.append("xmlns:");
sb.append(entry.getKey());
} else {
sb.append("xmlns");
}
sb.append("=\"");
sb.append(entry.getValue());
sb.append("\" ");
}
final String ret = sb.toString();
logger.debug("Stringified namespaces : [{}]", ret);
return ret;
}
/**
* Add namespaces to a {@link InputSource XML document}.
*
* @param inputSource the input source for the XML document.
* @param namespaces the map of namespaces prefixes and URIs.
* @return the modified document.
*/
public static Document addNamespacesToRootNode(@NonNull final InputSource inputSource,
@NonNull final Map namespaces) {
final Document ret;
try {
ret = XmlDocumentBuilder.of(inputSource).build();
Element element = ret.getDocumentElement();
ret.setStrictErrorChecking(false);
for (Map.Entry elm : namespaces.entrySet()) {
if (StringUtils.isNotBlank(elm.getValue())) {
element.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:" + elm.getKey(), elm.getValue());
}
}
} catch (final Exception exc) {
throw new SystemException(XmlErrorType.ERROR_PARSING_XML, exc);
}
return ret;
}
}