jlibs.xml.dom.DOMUtil Maven / Gradle / Ivy
/**
* Copyright 2015 Santhosh Kumar Tekuri
*
* The JLibs authors license this file to you 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 jlibs.xml.dom;
import jlibs.core.lang.Util;
import jlibs.xml.Namespaces;
import jlibs.xml.sax.SAXDelegate;
import jlibs.xml.xsl.TransformerUtil;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.BitSet;
import static javax.xml.XMLConstants.XMLNS_ATTRIBUTE;
/**
* @author Santhosh Kumar T
*/
public class DOMUtil{
/*-------------------------------------------------[ Builder ]---------------------------------------------------*/
public static DocumentBuilder newDocumentBuilder(boolean nsAware, boolean validating) throws ParserConfigurationException{
return newDocumentBuilder(nsAware, validating, false, false);
}
public static DocumentBuilder newDocumentBuilder(boolean nsAware, boolean validating, boolean coalescing, boolean ignoreComments) throws ParserConfigurationException{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(nsAware);
factory.setValidating(validating);
factory.setCoalescing(coalescing);
factory.setIgnoringComments(ignoreComments);
return factory.newDocumentBuilder();
}
/*-------------------------------------------------[ Namespace ]---------------------------------------------------*/
public static boolean isNamespaceDeclaration(Attr attr){
return Namespaces.URI_XMLNS.equals(attr.getNamespaceURI());
}
public static Attr findNamespaceDeclarationForPrefix(Node node, String prefix){
while(node!=null){
NamedNodeMap attrs = node.getAttributes();
if(attrs!=null){
for(int i=attrs.getLength()-1; i>=0; i--){
Attr attr = (Attr)attrs.item(i);
if(isNamespaceDeclaration(attr) && prefix.equals(attr.getLocalName()))
return attr;
}
}
node = node.getParentNode();
}
return null;
}
public static Attr findNamespaceDeclarationForURI(Node node, String uri){
while(node!=null){
NamedNodeMap attrs = node.getAttributes();
if(attrs!=null){
for(int i=attrs.getLength()-1; i>=0; i--){
Attr attr = (Attr)attrs.item(i);
if(isNamespaceDeclaration(attr) && uri.equals(attr.getNodeValue()))
return attr;
}
}
node = node.getParentNode();
}
return null;
}
/*-------------------------------------------------[ Equality ]---------------------------------------------------*/
public static boolean equals(Node node1, Node node2){
if(node1==node2)
return true;
Node n1 = node1;
Node n2 = node2;
while(true){
if(!shallowEquals(n1, n2))
return false;
if(n1==null){
assert n2==null;
return true;
}
Node n1Child = null;
if(n1.getNodeType()==Node.DOCUMENT_NODE || n1.getNodeType()==Node.ELEMENT_NODE)
n1Child = n1.getFirstChild(); // the jdk's dom impl returns non-null child for attribute etc
Node n2Child = null;
if(n2.getNodeType()==Node.DOCUMENT_NODE || n2.getNodeType()==Node.ELEMENT_NODE)
n2Child = n2.getFirstChild(); // the jdk's dom impl returns non-null child for attribute etc
if(!shallowEquals(n1Child, n2Child))
return false;
if(n1Child==null){
assert n2Child==null;
if(n1==node1 && n2==node2)
return true;
while(true){
Node n1Sibling = n1.getNextSibling();
Node n2Sibling = n2.getNextSibling();
if(!shallowEquals(n1Sibling, n2Sibling))
return false;
if(n1Sibling==null){
assert n2Sibling==null;
Node n1Parent = n1.getParentNode();
Node n2Parent = n2.getParentNode();
if(n1Parent==null && n2Parent==null)
return true;
if(n1Parent==node1 && n2Parent==node2)
return true;
assert n1Parent!=null && n2Parent!=null;
n1 = n1Parent;
n2 = n2Parent;
}else{
assert n2Sibling!=null;
n1 = n1Sibling;
n2 = n2Sibling;
break;
}
}
}else{
n1 = n1Child;
n2 = n2Child;
}
}
}
private static boolean shallowEquals(Node n1, Node n2){
if(n1==n2)
return true;
if(n1==null || n2==null)
return false;
int type1 = n1.getNodeType();
if(type1==Node.CDATA_SECTION_NODE)
type1 = Node.TEXT_NODE;
int type2 = n2.getNodeType();
if(type2==Node.CDATA_SECTION_NODE)
type2 = Node.TEXT_NODE;
if(type1!=type2)
return false;
switch(type1){
case Node.PROCESSING_INSTRUCTION_NODE:
ProcessingInstruction pi1 = (ProcessingInstruction)n1;
ProcessingInstruction pi2 = (ProcessingInstruction)n2;
if(!pi1.getTarget().equals(pi1.getTarget())
|| !pi1.getData().equals(pi2.getData()))
return false;
break;
case Node.COMMENT_NODE:
Comment comment1 = (Comment)n1;
Comment comment2 = (Comment)n2;
if(!comment1.getData().equals(comment2.getData()))
return false;
break;
case Node.ELEMENT_NODE:
Element element1 = (Element)n1;
Element element2 = (Element)n2;
String namespaceURI1 = element1.getNamespaceURI();
if(namespaceURI1==null)
namespaceURI1 = "";
String namespaceURI2 = element2.getNamespaceURI();
if(namespaceURI2==null)
namespaceURI2 = "";
if(!namespaceURI1.equals(namespaceURI2)
|| !element1.getLocalName().equals(element2.getLocalName()))
return false;
NamedNodeMap attrs1 = element1.getAttributes();
NamedNodeMap attrs2 = element2.getAttributes();
BitSet bitSet = new BitSet();
for(int i=0; i");
break;
case Node.PROCESSING_INSTRUCTION_NODE:
out.print("");
out.print(node.getNodeName());
out.print(' ');
out.print(node.getNodeValue());
out.print("?>");
break;
default:
try{
Transformer transformer = TransformerUtil.newTransformer(null, true, 0, null);
transformer.transform(new DOMSource(node), new StreamResult(out));
}catch(TransformerException ex){
throw new RuntimeException(ex);
}
}
}
/*-------------------------------------------------[ Misc ]---------------------------------------------------*/
public static void toSAX(Node root, SAXDelegate handler) throws SAXException{
DOMLocator locator = new DOMLocator();
switch(root.getNodeType()){
case Node.DOCUMENT_NODE:
break;
case Node.ELEMENT_NODE:
handler.setDocumentLocator(locator);
handler.startDocument();
if(root.getParentNode()!=null){
DOMNamespaceContext.Iterator iter = new DOMNamespaceContext.Iterator(root.getParentNode());
while(iter.hasNext())
handler.startPrefixMapping(iter.next(), iter.getNamespaceURI());
}
break;
default:
throw new IllegalArgumentException("Node must be Document or Element");
}
Node node = root;
AttributesImpl attrs = new AttributesImpl();
while(node!=null){
locator.node = node;
switch(node.getNodeType()){
case Node.DOCUMENT_NODE:
handler.setDocumentLocator(locator);
handler.startDocument();
break;
case Node.DOCUMENT_TYPE_NODE:
DocumentType docType = (DocumentType)node;
handler.startDTD(docType.getName(), docType.getPublicId(), docType.getSystemId());
break;
case Node.ELEMENT_NODE:
attrs.clear();
NamedNodeMap nodeAttrs = node.getAttributes();
if(nodeAttrs!=null){
for(int i=nodeAttrs.getLength()-1; i>=0; i--){
Node attr = nodeAttrs.item(i);
if(XMLNS_ATTRIBUTE.equals(attr.getNodeName()))
handler.startPrefixMapping("", attr.getNodeValue());
else if(XMLNS_ATTRIBUTE.equals(attr.getPrefix()))
handler.startPrefixMapping(attr.getLocalName(), attr.getNodeValue());
else
attrs.addAttribute(attr.getNamespaceURI(), attr.getLocalName(), attr.getNodeName(), "CDATA", attr.getNodeValue());
}
}
handler.startElement(node.getNamespaceURI(), node.getLocalName(), node.getNodeName(), attrs);
break;
case Node.TEXT_NODE:
char chars[] = node.getNodeValue().toCharArray();
handler.characters(chars, 0, chars.length);
break;
case Node.CDATA_SECTION_NODE:
chars = node.getNodeValue().toCharArray();
handler.startCDATA();
handler.characters(chars, 0, chars.length);
handler.endCDATA();
break;
case Node.PROCESSING_INSTRUCTION_NODE:
ProcessingInstruction pi = (ProcessingInstruction)node;
handler.processingInstruction(pi.getTarget(), pi.getData());
break;
case Node.COMMENT_NODE:
chars = node.getNodeValue().toCharArray();
handler.comment(chars, 0, chars.length);
}
NodeList children = node.getChildNodes();
if(children!=null && children.getLength()>0)
node = children.item(0);
else{
while(true){
locator.node = node;
switch(node.getNodeType()){
case Node.ELEMENT_NODE:
handler.endElement(node.getNamespaceURI(), node.getLocalName(), node.getNodeName());
NamedNodeMap nodeAttrs = node.getAttributes();
if(nodeAttrs!=null){
for(int i=nodeAttrs.getLength()-1; i>=0; i--){
Node attr = nodeAttrs.item(i);
if(XMLNS_ATTRIBUTE.equals(attr.getNodeName()))
handler.endPrefixMapping("");
else if(XMLNS_ATTRIBUTE.equals(attr.getPrefix()))
handler.endPrefixMapping(attr.getLocalName());
}
}
break;
case Node.DOCUMENT_TYPE_NODE:
handler.endDTD();
break;
}
if(node==root){
if(root.getNodeType()==Node.ELEMENT_NODE && root.getParentNode()!=null){
DOMNamespaceContext.Iterator iter = new DOMNamespaceContext.Iterator(root.getParentNode());
while(iter.hasNext())
handler.endPrefixMapping(iter.next());
}
handler.endDocument();
return;
}
if(node.getNextSibling()!=null){
node = node.getNextSibling();
break;
}else
node = node.getParentNode();
}
}
}
}
public static int getPosition(Element elem){
int pos = 1;
NodeList list = elem.getParentNode().getChildNodes();
for(int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy