/**
* Copyright 2014
* SMEdit https://github.com/StarMade/SMEdit
* SMTools https://github.com/StarMade/SMTools
*
* 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 jo.sm.logic.utils;
import java.io.File;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Attr;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
public class XMLEditUtils {
private static final Logger log = Logger.getLogger(XMLEditUtils.class.getName());
public static Node addTextTag(Node parent, String name, String value) {
Node node = parent.getOwnerDocument().createElement(name);
parent.appendChild(node);
Text text = parent.getOwnerDocument().createTextNode(value);
node.appendChild(text);
return node;
}
public static Node addText(Node parent, String value) {
Text text = parent.getOwnerDocument().createTextNode(value);
parent.appendChild(text);
return text;
}
public static Element addElement(Node parent, String name) {
Element node;
if (parent.getOwnerDocument() != null) {
node = parent.getOwnerDocument().createElement(name);
} else if (parent instanceof Document) {
node = ((Document) parent).createElement(name);
} else {
return null;
}
parent.appendChild(node);
return node;
}
public static Attr addAttribute(Node parent, String name, String value) {
if (value == null) {
return null;
}
Attr node = parent.getOwnerDocument().createAttribute(name);
try {
node.setValue(value);
parent.getAttributes().setNamedItem(node);
} catch (DOMException e) {
log.log(Level.WARNING, "Problem rewriting " + parent.getNodeName() + "." + name + "='" + node.getValue() + "' -> '" + value + "'");
System.out.println("Problem rewriting " + parent.getNodeName() + "." + name + "='" + node.getValue() + "' -> '" + value + "'");
}
return node;
}
public static void removeAttribute(Node parent, String name, String value, boolean recursive) {
NamedNodeMap nnm = parent.getAttributes();
if (nnm != null) {
if (value == null) {
nnm.removeNamedItem(name);
} else {
Node attr = nnm.getNamedItem(name);
if (attr != null) {
String attrVal = attr.getNodeValue();
if (value.equals(attrVal)) {
nnm.removeNamedItem(name);
}
}
}
}
if (recursive) {
for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
removeAttribute(child, name, value, recursive);
}
}
}
public static Node duplicate(Node node, Document ownerDocument) {
if (node instanceof Text) {
return ownerDocument.createTextNode(node.getNodeValue());
}
if (node instanceof Comment) {
return ownerDocument.createComment(node.getNodeValue());
}
Node newNode = ownerDocument.createElement(node.getNodeName());
NamedNodeMap attribs = node.getAttributes();
for (int i = 0; i < attribs.getLength(); i++) {
Node attrib = attribs.item(i);
addAttribute(newNode, attrib.getNodeName(), attrib.getNodeValue());
}
for (Node n = node.getFirstChild(); n != null; n = n.getNextSibling()) {
Node newN = duplicate(n, ownerDocument);
newNode.appendChild(newN);
}
return newNode;
}
public static void join(Node target, Node source) {
for (Node s = source.getFirstChild(); s != null; s = s.getNextSibling()) {
if (s.getNodeName().startsWith("#")) {
continue;
}
Node t = findIdentical(target, s);
if (t == null) {
t = duplicate(s, target.getOwnerDocument());
target.appendChild(t);
} else {
join(t, s);
}
}
}
private static Node findIdentical(Node target, Node s) {
NamedNodeMap sAttrs = s.getAttributes();
String sText = XMLUtils.getText(s).trim();
for (Node t = target.getFirstChild(); t != null; t = t.getNextSibling()) {
if (!t.getNodeName().equals(s.getNodeName())) {
continue;
}
NamedNodeMap tAttrs = t.getAttributes();
if (sAttrs.getLength() != tAttrs.getLength()) {
continue;
}
boolean allMatch = true;
for (int i = 0; i < sAttrs.getLength(); i++) {
Node attr = sAttrs.item(i);
String key = attr.getNodeName();
String val = attr.getNodeValue();
if (!val.equals(XMLUtils.getAttribute(t, key))) {
allMatch = false;
break;
}
}
if (!allMatch) {
continue;
}
String tText = XMLUtils.getText(t).trim();
if (!sText.equals(tText)) {
continue;
}
return t;
}
return null;
}
public static void merge(Node target, Node source) {
for (Node s = source.getFirstChild(); s != null; s = s.getNextSibling()) {
if (s.getNodeName().startsWith("#")) {
continue;
}
String id = XMLUtils.getAttribute(s, "id");
// find target
Node t;
for (t = target.getFirstChild(); t != null; t = t.getNextSibling()) {
if (t.getNodeName().equals(s.getNodeName())) {
if (StringUtils.isTrivial(id) || id.equals(XMLUtils.getAttribute(t, "id"))) {
break;
}
}
}
if (t != null) {
merge(t, s);
} else {
t = duplicate(s, target.getOwnerDocument());
target.appendChild(t);
}
}
}
public static void removeAllChildren(Node node) {
while (node.getFirstChild() != null) {
node.removeChild(node.getFirstChild());
}
}
public static void setInnerXML(Node node, String xml) {
removeAllChildren(node);
Document doc = XMLUtils.readString("<html>" + xml + "</html>"); // must give root element
if ((doc != null) && (doc.getFirstChild() != null)) {
for (Node n = doc.getFirstChild().getFirstChild(); n != null; n = n.getNextSibling()) {
try {
Node dup = duplicate(n, node.getOwnerDocument());
node.appendChild(dup);
} catch (DOMException e) {
log.log(Level.WARNING, "Problem adding duplicate for '" + XMLUtils.writeString(n) + "'");
log.log(Level.WARNING, "Full text: '" + xml + "'");
System.out.println("Problem adding duplicate for '" + XMLUtils.writeString(n) + "'");
System.out.println("Full text: '" + xml + "'");
e.printStackTrace();
}
}
}
}
public static void copyAttributes(Node from, Node to) {
NamedNodeMap map = from.getAttributes();
for (int i = 0; i < map.getLength(); i++) {
Node attr = map.item(i);
addAttribute(to, attr.getNodeName(), attr.getNodeValue());
}
}
public static void merge(File file1, String point1, File file2, String point2, File file3) {
Document doc1 = XMLUtils.readFile(file1);
Document doc2 = XMLUtils.readFile(file2);
List<Node> points1 = XMLUtils.findNodes(doc1, point1);
List<Node> points2 = XMLUtils.findNodes(doc2, point2);
for (int i = 0; i < Math.min(points1.size(), points2.size()); i++) {
Node node1 = points1.get(i);
Node node2 = points2.get(i);
Node dup1 = duplicate(node1, node2.getOwnerDocument());
node2.getParentNode().replaceChild(dup1, node2);
}
XMLUtils.writeFile(doc2.getFirstChild(), file3);
}
public static void replaceText(Node node, String text) {
for (;;) {
Node n = node.getFirstChild();
if (n == null) {
break;
}
node.removeChild(n);
}
Text t = node.getOwnerDocument().createTextNode(text);
node.appendChild(t);
}
public static Node addElementAndAttributes(Node parent, String name, String[] atts) {
Node n = addElement(parent, name);
for (int i = 0; i < atts.length; i += 2) {
addAttribute(n, atts[i], atts[i + 1]);
}
return n;
}
public static void addAtEndOfGroup(Node parent, Node newChild) {
addAtEndOfGroup(parent, newChild.getNodeName(), newChild);
}
public static void addAtEndOfGroup(Node parent, String childType, Node newChild) {
List<Node> peers = XMLUtils.findNodes(parent, childType);
if (peers.isEmpty()) {
parent.appendChild(newChild);
} else {
Node lastPeer = peers.get(peers.size() - 1);
if (lastPeer.getNextSibling() == null) {
parent.appendChild(newChild);
} else {
parent.insertBefore(newChild, lastPeer.getNextSibling());
}
}
}
}