328 lines
10 KiB
Java
328 lines
10 KiB
Java
package tools.xmltools;
|
||
|
||
import javax.xml.parsers.ParserConfigurationException;
|
||
import javax.xml.xpath.XPath;
|
||
import javax.xml.xpath.XPathExpression;
|
||
|
||
import org.w3c.dom.CharacterData;
|
||
import org.w3c.dom.Document;
|
||
import org.w3c.dom.Element;
|
||
import org.w3c.dom.NamedNodeMap;
|
||
import org.w3c.dom.Node;
|
||
import org.w3c.dom.NodeList;
|
||
import org.w3c.dom.ls.DOMImplementationLS;
|
||
import org.w3c.dom.ls.LSSerializer;
|
||
import org.xml.sax.SAXException;
|
||
|
||
import javax.xml.xpath.XPath;
|
||
import javax.xml.xpath.XPathConstants;
|
||
import javax.xml.xpath.XPathExpression;
|
||
import javax.xml.xpath.XPathExpressionException;
|
||
import javax.xml.xpath.XPathFactory;
|
||
import java.io.ByteArrayInputStream;
|
||
import java.io.IOException;
|
||
import java.io.InputStream;
|
||
|
||
/**
|
||
* Created by IntelliJ IDEA.
|
||
* User: Igor
|
||
* Date: 18.12.2005
|
||
* Time: 15:26:59
|
||
* To change this template use File | Settings | File Templates.
|
||
*/
|
||
public class XMLTools
|
||
{
|
||
/**
|
||
* Вернуть значение первой попавшийся CDATA
|
||
* @return строка
|
||
*/
|
||
public static String getCDATAValue(Node node)
|
||
{
|
||
if(node==null) return "";
|
||
NodeList items = node.getChildNodes();
|
||
for (int i=0;i<items.getLength();i++)
|
||
{
|
||
Node n=items.item(i);
|
||
if(n.getNodeName().equals("#cdata-section"))
|
||
return n.getNodeValue();
|
||
}
|
||
return "";
|
||
}
|
||
|
||
public static Document parse(String xmlString) throws IOException, ParserConfigurationException, SAXException
|
||
{
|
||
return XMLIO.load(new ByteArrayInputStream(xmlString.getBytes()));
|
||
}
|
||
|
||
public static Document parse(InputStream xmlString) throws IOException, ParserConfigurationException, SAXException
|
||
{
|
||
return XMLIO.load(xmlString);
|
||
}
|
||
|
||
/**
|
||
* Возвращает вложенный элемент "childName" элемента "parent" <br/>
|
||
* <element><childName/></element>
|
||
* @param parent
|
||
* @param childName
|
||
* @return Дочерный элемент либо <code>null</code>, если элементов с таким именем нет
|
||
*/
|
||
public static Element getChild(Element parent, String childName){
|
||
NodeList nl = parent.getChildNodes();
|
||
for (int i = 0; i <nl.getLength(); i++) {
|
||
if (isElement(nl.item(i), childName)){
|
||
return (Element)nl.item(i);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Проверяет, является ли <code>node</code> элементом (<code>instanceOf {@link Element}</code>)
|
||
* и имеет ли имя "tagname"
|
||
* @param node
|
||
* @param tagname
|
||
* @return
|
||
*/
|
||
public static boolean isElement(Node node, String tagname){
|
||
return node instanceof Element && node.getNodeName().equals(tagname);
|
||
}
|
||
|
||
//вернуть первый попавшийся узел среди дочерних
|
||
public static Node getFirstNodeOnName(Node node,String nodename)
|
||
{
|
||
Node[] mas=new Node[50]; //depth
|
||
int pos=0;
|
||
mas[pos] = node.getFirstChild();
|
||
while (mas[pos] != null)
|
||
{
|
||
if(mas[pos].getNodeName().equals(nodename))
|
||
{
|
||
return mas[pos];
|
||
}
|
||
if(mas[pos].getFirstChild()!=null)
|
||
{
|
||
pos++;
|
||
mas[pos]=mas[pos-1].getFirstChild();
|
||
}else
|
||
{
|
||
//если не идёт дальше пытаемся подняться в верх по дереву
|
||
while (true)
|
||
{
|
||
mas[pos] = mas[pos].getNextSibling();
|
||
if (mas[pos]==null)
|
||
{
|
||
if(pos>0){ pos--; }else{ break; }
|
||
}else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Return first from childs in first deep level on name
|
||
* @param node Find in
|
||
* @param nodename Name node
|
||
* @return node
|
||
*/
|
||
public static Node getNodeOnName(Node node,String nodename)
|
||
{
|
||
if(node==null) return null;
|
||
Node nextNode = node.getFirstChild();
|
||
while(nextNode != null)
|
||
{
|
||
if(nextNode.getNodeName().equals(nodename)) return nextNode;
|
||
nextNode=nextNode.getNextSibling();
|
||
}
|
||
return null;
|
||
}
|
||
|
||
//Сериализовать узел в строку
|
||
public static String getOuterXML(Node node)
|
||
{
|
||
DOMImplementationLS domImplementation = (DOMImplementationLS) node.getOwnerDocument().getImplementation();
|
||
LSSerializer lsSerializer = domImplementation.createLSSerializer();
|
||
if (!(node instanceof Document))
|
||
{
|
||
lsSerializer.getDomConfig().setParameter("xml-declaration", false);
|
||
}
|
||
return lsSerializer.writeToString(node);
|
||
}
|
||
|
||
public static Node findFirstNodeOnAttribute(Node node, String nodename,String attribute,String val)
|
||
{
|
||
Node result=null;
|
||
if(node==null) return result;
|
||
javax.xml.xpath.XPathFactory xPathfactory = javax.xml.xpath.XPathFactory.newInstance();
|
||
XPath xpath = xPathfactory.newXPath();
|
||
XPathExpression expr=null;
|
||
Object exprResult=null;
|
||
try {
|
||
expr = xpath.compile("//*/"+nodename+"[@"+attribute+"='" + val + "']");
|
||
exprResult = expr.evaluate(node, XPathConstants.NODESET);
|
||
} catch (XPathExpressionException ex) {
|
||
|
||
}
|
||
NodeList nodeList = (NodeList) exprResult;
|
||
if (nodeList.getLength() > 0)
|
||
result = nodeList.item(0);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Поиск среди текущего и дочерних узлов
|
||
* @param {Node} node Корневой узел
|
||
* @param {String} nodename Имя первого попавшегося узла
|
||
* @returns {undefined}
|
||
*/
|
||
public static Node findFirstNode(Node node, String nodename)
|
||
{
|
||
Node result=null;
|
||
if(node==null) return result;
|
||
javax.xml.xpath.XPathFactory xPathfactory = javax.xml.xpath.XPathFactory.newInstance();
|
||
XPath xpath = xPathfactory.newXPath();
|
||
XPathExpression expr=null;
|
||
Object exprResult=null;
|
||
try {
|
||
expr = xpath.compile("//*/"+nodename);
|
||
exprResult = expr.evaluate(node, XPathConstants.NODESET);
|
||
} catch (XPathExpressionException ex) {
|
||
|
||
}
|
||
NodeList nodeList = (NodeList) exprResult;
|
||
if (nodeList.getLength() > 0)
|
||
result = nodeList.item(0);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Найти узел по имени
|
||
* @param node
|
||
* @param nodename
|
||
* @return
|
||
*/
|
||
public static Node findFirstNode_v2(Node node, String nodename)
|
||
{
|
||
if(node==null || nodename==null) return null;
|
||
NodeList items = node.getChildNodes();
|
||
for (int i=0;i<items.getLength();i++)
|
||
{
|
||
Node n=items.item(i);
|
||
if(n.getNodeName().equals(nodename))
|
||
{
|
||
return n;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/** Найти узел по атрибуту
|
||
*/
|
||
public static Node findNodeOnAttribute(Node node, String nodename, String attribute, String val)
|
||
{
|
||
if(node==null) return null;
|
||
NodeList items = node.getChildNodes();
|
||
for (int i=0;i<items.getLength();i++)
|
||
{
|
||
Node n=items.item(i);
|
||
if(n.getNodeName().equals(nodename))
|
||
{
|
||
NamedNodeMap nnm=n.getAttributes();
|
||
if(nnm.getNamedItem(attribute).getNodeValue().equals(val)) return n;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Присвоить дочерние узлы первого дерева второму если их нет, иначе дополнить либо заменить. (Работает через рекурсию нужно для передачи параметров между окнами)
|
||
* @param {XML} first Узел где ханятся настройки
|
||
* @param {XML} second Узел к которому применяются настройки
|
||
* @param {String} name Имя атрибута по которому будут находиться одинаковые XML узлы
|
||
* @returns {undefined}
|
||
*/
|
||
public static void applyNodeToNode(Node first, Node second,String name)
|
||
{
|
||
if(first==null || second==null || name==null) return;
|
||
|
||
//Если есть совпадающие узлы то передаём в рекурсию если нет то просто копируем
|
||
Node fn=first.getFirstChild();
|
||
while (fn != null)
|
||
{
|
||
Node sn=null;
|
||
if(!fn.getNodeName().equals("#text") && !fn.getNodeName().equals("#cdata-section") && !fn.getNodeName().equals("#comment")) { //потому что для этих getAttribute вызывает ошибку
|
||
sn=findNodeOnAttribute(second,fn.getNodeName(),name,fn.getAttributes().getNamedItem(name).getNodeValue());
|
||
}
|
||
|
||
if(sn!=null) //Если по имени атрибуту совпали узлы
|
||
{
|
||
//Переписываем значения атрибутов из первого второму, если их нет то создаём.
|
||
for(int i=0;i<fn.getAttributes().getLength();i++)
|
||
{
|
||
Element el=(Element) sn;
|
||
el.setAttribute(fn.getAttributes().item(i).getNodeName(),fn.getAttributes().item(i).getNodeValue());
|
||
}
|
||
applyNodeToNode(fn,sn,name); //В рекурсию
|
||
}
|
||
else
|
||
{
|
||
//Значения CDADA или text node не должны накапливаться их мы пересоздаём (потом по момеру можно сделать 1й заменяется первым итд.)
|
||
if(fn.getNodeName().equals("#cdata-section"))
|
||
{
|
||
XMLTools.setCharacterDataToElement((Element)second, XMLTools.getCharacterDataFromElement((Element) fn)); //getCdata(second).nodeValue = fn.nodeValue;
|
||
}else
|
||
{
|
||
second.appendChild(fn.cloneNode(true));
|
||
}
|
||
}
|
||
fn=fn.getNextSibling();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Найти узел по имени
|
||
* @param node
|
||
* @param nodename
|
||
* @return
|
||
*/
|
||
public static Node findNode(Node node, String nodename)
|
||
{
|
||
if(node==null || nodename==null) return null;
|
||
NodeList items = node.getChildNodes();
|
||
for (int i=0;i<items.getLength();i++)
|
||
{
|
||
Node n=items.item(i);
|
||
if(n.getNodeName().equals(nodename))
|
||
{
|
||
return n;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public static String getCharacterDataFromElement(Element e) {
|
||
Node child = e.getFirstChild();
|
||
if (child instanceof CharacterData) {
|
||
CharacterData cd = (CharacterData) child;
|
||
return cd.getData().trim();
|
||
}
|
||
return "";
|
||
}
|
||
|
||
public static void setCharacterDataToElement(Node nF, String data) {
|
||
Node child = nF.getFirstChild();
|
||
if (child instanceof CharacterData) {
|
||
CharacterData cd = (CharacterData) child;
|
||
cd.setData(data);
|
||
} else //Create new CDATA node
|
||
{
|
||
Document doc = nF.getOwnerDocument();
|
||
nF.appendChild(doc.createCDATASection(data));
|
||
}
|
||
}
|
||
|
||
}
|