package com.intuit.tank.http.xml; /* * #%L * Intuit Tank Agent (apiharness) * %% * Copyright (C) 2011 - 2015 Intuit Inc. * %% * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * #L% */ import java.io.File; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPathFactory; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.Namespace; import org.jdom.input.SAXBuilder; import org.jdom.output.XMLOutputter; import org.jdom.xpath.XPath; import org.xml.sax.InputSource; /** * Generic class to provide xml file reading and writing capabilities */ public class GenericXMLHandler implements Cloneable { static Logger LOG = LogManager.getLogger(GenericXMLHandler.class); protected Document xmlDocument = null; protected File xmlFile = null; protected HashMap<String, String> namespaces; protected String xml; private org.w3c.dom.Document dDoc; /** * Constructor */ public GenericXMLHandler() { try { this.xmlDocument = new Document(); this.namespaces = new HashMap<String, String>(); } catch (Exception ex) { LOG.error("Error initializing handler: " + ex.getMessage(), ex); } } /** * Constructor * * @param xmlFile * The xml file to load */ public GenericXMLHandler(File xmlFile) { try { this.xmlFile = xmlFile; this.xmlDocument = new org.jdom.Document(); SAXBuilder builder = new SAXBuilder(); builder.setValidation(false); this.xmlDocument = builder.build(this.xmlFile); this.namespaces = new HashMap<String, String>(); } catch (Exception ex) { this.xmlDocument = null; LOG.error("Error initializing handler: " + ex.getMessage(), ex); } } /** * Constructor * * @param xmlFile * The string representation of the xml data */ public GenericXMLHandler(String xmlFile) { if (StringUtils.isNotEmpty(xmlFile)) { this.xml = xmlFile; try { this.xmlFile = null; this.xmlDocument = new org.jdom.Document(); SAXBuilder builder = new SAXBuilder(); builder.setValidation(false); // LOG.debug("XML string to load: "+xmlFile); xmlFile = xmlFile.substring(xmlFile.indexOf("<")); this.xmlDocument = builder.build(new StringReader(xmlFile)); this.namespaces = new HashMap<String, String>(); InputSource is = new InputSource(new StringReader(xml)); this.dDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(is); } catch (Exception ex) { this.xmlDocument = null; LOG.error("Error parsing xml Response: " + xmlFile + ": " + ex.getMessage()); } } } /** * Set the element's text value * * @param xPathExpression * The xpath expression for the element * @param value * The value to set the text to */ public void SetElementText(String xPathExpression, String value) { Element node; try { node = SetElementText(xPathExpression, 0); node.setText(value); } catch (Exception ex) { LOG.error("Error in handler: " + ex.getMessage(), ex); } } public void SetElementAttribute(String xPathExpression, String attribute, String value) { Element node; try { node = SetElementText(xPathExpression, 0); node.setAttribute(attribute, value); } catch (Exception ex) { LOG.error("Error in handler: " + ex.getMessage(), ex); } } /** * Set the element's text value * * @param xPathExpression * The xpath expression for the element * @param value * The value to set the text to * @throws JDOMException */ private Element SetElementText(String xPathExpression, int currentNode) throws JDOMException { String currentPath = getCurrentPath(xPathExpression, currentNode); if (xPathExists(currentPath)) { if (currentPath.equals(xPathExpression)) { org.jdom.Element node = (org.jdom.Element) XPath.selectSingleNode(this.xmlDocument, xPathExpression); return node; } else { return SetElementText(xPathExpression, currentNode + 1); } } else { String childNode = getChildNode(currentPath); String namespace = getCurrentNamespace(currentPath); Element element; if (namespace != null) { Namespace sNS = Namespace.getNamespace(namespace, this.namespaces.get(namespace)); element = new Element(childNode, sNS); // element.setAttribute("someKey", "someValue", Namespace.getNamespace("someONS", // "someOtherNamespace")); } else { element = new Element(childNode); } if (this.xmlDocument.hasRootElement()) { Element node = (Element) XPath.selectSingleNode(this.xmlDocument, getParentPath(currentPath)); node.addContent(element); } else { if (this.xmlDocument.hasRootElement()) { this.xmlDocument.detachRootElement(); } this.xmlDocument.addContent(element); } if (currentPath.equals(xPathExpression)) { return element; } else { return SetElementText(xPathExpression, currentNode + 1); } } } /** * Get the text for the selected element * * @param xPathExpression * The xpath expression for the element * @return The text value of the element */ public String GetElementText(String xPathExpression) { try { String result = XPathFactory.newInstance().newXPath().evaluate(xPathExpression, dDoc); if (StringUtils.isNotEmpty(result)) { return result; } return ""; } catch (Exception ex) { LOG.error("Error in handler: " + ex.getMessage(), ex); return ""; } } /** * Get the text for the selected element * * @param xPathExpression * The xpath expression for the element * @return The text value of the element */ public String GetElementAttr(String xPathExpression) { try { org.jdom.Attribute node = (Attribute) XPath.selectSingleNode(this.xmlDocument, xPathExpression); return node.getValue(); } catch (Exception ex) { LOG.error("Error in handler: " + ex.getMessage(), ex); return ""; } } /** * Retrieves the text elements for a given xpath expression * * @param xPathExpression * @return */ public ArrayList<String> GetElementList(String xPathExpression) { try { ArrayList<String> values = new ArrayList<String>(); List<?> nodeList = XPath.selectNodes(this.xmlDocument, xPathExpression); Iterator<?> iter = nodeList.iterator(); while (iter.hasNext()) { org.jdom.Element element = (org.jdom.Element) iter.next(); values.add(element.getText()); } return values; } catch (Exception ex) { LOG.error("Error in handler: " + ex.getMessage(), ex); return null; } } /** * Does an xPath expression exist * * @param xpathExpr * The xPath expression * @return TRUE if the xPath expression exists; false otherwise */ public boolean xPathExists(String xpathExpr) { try { if (XPath.selectSingleNode(this.xmlDocument, xpathExpr) == null) return false; return true; } catch (Exception ex) { return false; } } /** * Return the xml document in a String object */ public String toString() { if (this.xmlDocument != null) { XMLOutputter outputter = new XMLOutputter(); String output = outputter.outputString(this.xmlDocument); output = output.replaceAll("\r", ""); output = output.replaceAll("\n", ""); output = output.replaceAll("\t", ""); return output; } return ""; } /** * Save the xml to a file */ public void Save() { try { XMLOutputter out = new XMLOutputter(); java.io.FileWriter writer = new java.io.FileWriter(this.xmlFile); out.output(this.xmlDocument, writer); writer.flush(); writer.close(); } catch (Exception ex) { LOG.error("Error in handler: " + ex.getMessage(), ex); } } public boolean isXMLValid() { if (this.xmlDocument == null) return false; return true; } /** * Clone the object */ public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(e.toString()); } } /** * * * @param xpath * @return */ public String getParentPath(String xpath) { String[] paths = xpath.split("/"); String newPath = ""; for (int i = 1; i <= paths.length - 2; i++) { newPath = newPath + "/" + paths[i]; } return newPath; } /** * * * @param xpath * @return */ public String getCurrentPath(String xpath, int node) { String[] paths = xpath.split("/"); String newPath = ""; for (int i = 0; i <= node; i++) { newPath = newPath + "/" + paths[i + 1]; } return newPath; } /** * * @param xpath * @return */ public String getChildNode(String xpath) { String[] paths = xpath.split("/"); String node = paths[paths.length - 1]; if (node.contains(":")) { node = node.substring(node.indexOf(":") + 1); } return node; } public String getCurrentNamespace(String xpath) { String[] paths = xpath.split("/"); String node = paths[paths.length - 1]; if (node.contains(":")) { return node.substring(0, node.indexOf(":")); } return null; } public void setNamespace(String name, String value) { this.namespaces.put(name, value); } }