import java.io.*; import java.util.*; import org.jdom2.*; import org.jdom2.filter.Filters; import org.jdom2.input.SAXBuilder; import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; import org.jdom2.xpath.*; /** * Contains methods based on JDOM and Jaxen library that help processing XML files and other misc ones. */ public class XMLHelper { /** * Reads an .xml file from file path and returns a JDOM document. * * @param src The .xml file path * @return JDOM document * @throws JDOMException * @throws IOException */ public static Document readXml(String src) throws JDOMException, IOException { File file = new File(src); SAXBuilder saxBuilder = new SAXBuilder(); Document doc = saxBuilder.build(file); return doc; } /** * Saves the given Document as XML to the given path. * * @param oDoc The JDOM document * @param sPath The output path * @throws IOException */ public static void saveAsXml(Document oDoc, String sPath) throws IOException { FileOutputStream dest = new FileOutputStream(sPath); XMLOutputter xmlOutput = new XMLOutputter(); xmlOutput.setFormat(Format.getPrettyFormat()); xmlOutput.output(oDoc, dest); } /** * Takes a given directory path and lists all files directly in it. * (Does not visit sub-directories recursively) * * @param path Path to the directory * @return ArrayList with all file names */ public static ArrayList<String> getFileNames(String path) { ArrayList<String> fileNames = new ArrayList<String>(); File directory = new File(path); File[] contentList = directory.listFiles(); for (File file : contentList) { if (file.isFile()) fileNames.add(file.getName()); } return fileNames; } /** * Executes given XPath expression for elements with JDOM Document as source. * * @param doc The JDOM Document * @param xPath XPath expression * @return List with all elements found or empty list if no match found */ public static List<Element> xQueryElements(Document doc, String xPath) { XPathFactory xFactory = XPathFactory.instance(); XPathExpression<Element> expr = xFactory.compile(xPath, Filters.element()); List<Element> result = expr.evaluate(doc); return result; } /** * Executes given XPath expression for elements with Element as source. * (Expression is executed on the entire Document the Element is attached to!) * * @param elem The Element * @param xPath XPath expression * @return List with all elements found or empty list if no match found */ public static List<Element> xQueryElements(Element elem, String xPath) { XPathFactory xFactory = XPathFactory.instance(); XPathExpression<Element> expr = xFactory.compile(xPath, Filters.element()); List<Element> result = expr.evaluate(elem); return result; } /** * Executes given XPath expression for attributes with JDOM Document as source. * * @param doc The JDOM Document * @param xPath XPath expression * @return List with all attributes found or empty list if no match found */ public static List<Attribute> xQueryAttributes(Document doc, String xPath) { XPathFactory xFactory = XPathFactory.instance(); XPathExpression<Attribute> expr = xFactory.compile(xPath, Filters.attribute()); List<Attribute> result = expr.evaluate(doc); return result; } /** * Executes given XPath expression for attributes with Element as source. * (Expression is executed on the entire Document the Element is attached to!) * * @param elem The Element * @param xPath XPath expression * @return List with all attributes found or empty list if no match found */ public static List<Attribute> xQueryAttributes(Element elem, String xPath) { XPathFactory xFactory = XPathFactory.instance(); XPathExpression<Attribute> expr = xFactory.compile(xPath, Filters.attribute()); List<Attribute> result = expr.evaluate(elem); return result; } /** * Searches a document for the first occurrence of an XML tag with JDOM Document as source. * * @param doc The JDOM Document * @param elementName Name of the XML tag * @return First element found or NULL if no match found */ public static Element searchFirstElement(Document doc, String elementName) { //XPath index starts with 1; [] has a higher precedence than // List<Element> query= xQueryElements(doc, "(//"+elementName+")[1]"); if(query.isEmpty()) return null; return query.get(0); } /** * Searches a document for the first occurrence of an XML tag with Element as source. * (Expression is executed on the entire Document the Element is attached to!) * * @param elem The Element * @param elementName Name of the XML tag * @return First element found or NULL if no match found */ public static Element searchFirstElement(Element elem, String elementName) { //XPath index starts with 1; [] has a higher precedence than // List<Element> query= xQueryElements(elem, "(//"+elementName+")[1]"); if(query.isEmpty()) return null; return query.get(0); } /** * Searches a document for all occurrences of an XML tag with JDOM Document as source. * * @param doc The JDOM Document * @param elementName Name of the XML tag * @return List with all elements found or empty list if no match found */ public static List<Element> searchAllElements(Document doc, String elementName) { return xQueryElements(doc, "//"+elementName); } /** * Searches a document for all occurrences of an XML tag with Element as source. * (Expression is executed on the entire Document the Element is attached to!) * * @param elem The Element * @param elementName Name of the XML tag * @return List with all elements found or empty list if no match found */ public static List<Element> searchAllElements(Element elem, String elementName) { return xQueryElements(elem, "//"+elementName); } /** * Checks whether two elements have an equal XML tag. * (Name of the XML tag and all attributes including their order must be equal) * * @param element1 Element1 * @param element2 Element2 * @return true if of equal tag or false if not */ public static boolean equalTag(Element element1, Element element2) { List<Attribute> attributeList1 = element1.getAttributes(); List<Attribute> attributeList2 = element2.getAttributes(); if(!element1.getName().equals(element2.getName())) return false; if(attributeList1.size()!=attributeList2.size()) return false; for(int i=0; i<attributeList1.size(); i++) { if(!attributeList1.get(i).getName().equals(attributeList2.get(i).getName())) return false; if(!attributeList1.get(i).getValue().equals(attributeList2.get(i).getValue())) return false; } return true; } /** * Recursive replacement of all text values in destElements with their corresponding * new ones from srcElements. * (srcElements and destElements must be matching tags and have the same depth!) * * @param srcElements Element list with new values * @param destElements Element list with values to be replaced * @return true if reached deepest Element or false if not */ public static boolean replace(List<Element> srcElements, List<Element> destElements) { if(srcElements.isEmpty()&&destElements.isEmpty()) return true; if(srcElements.isEmpty()^destElements.isEmpty()) { System.err.println("Error during value replacement: Sensor xml trees have mismatching deph (maybe tags with no value)"); System.exit(-1); } for(Element src : srcElements) { for(Element dest : destElements) { if(equalTag(src, dest)) { boolean deadEnd = replace(src.getChildren(), dest.getChildren()); if(deadEnd) dest.setText(src.getText()); break; } } } return false; } /** * @param args */ public static void main(String[] args) { } }