package com.kaltura.client.utils;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* XML parsing utilities for the Kaltura Java Client
*
* AZ Refactored this class on Thu 23 Jun 2011 11:33:10 EDT
*
* @author Aaron Zeckoski (azeckoski @ vt.edu) (azeckoski @ unicon.net)
*/
public class XmlUtils {
public static Element parseXml(String xml) {
Element root = null;
//get the factory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( new InputSource(new StringReader(xml)) );
root = doc.getDocumentElement();
} catch(ParserConfigurationException pce) {
//pce.printStackTrace();
} catch(SAXException se) {
//se.printStackTrace();
} catch(IOException ioe) {
//ioe.printStackTrace();
}
return root;
}
/**
* Finds the text value of the first tag within a given element
*
* @param element the XML element
* @param tagName the tag name
* @return the value in the tag OR null if the tagName is not set, element is not set, tagName is not found
*/
public static String getTextValue(Element element, String tagName) {
String textVal = null;
/* removed this because it depends on com.sun.org.apache.xpath.internal.XPathAPI
* this is a very bad practice - http://stackoverflow.com/questions/446315/which-xpathapi-should-i-use-in-java-1-5
* Commented on Thu 23 Jun 2011 15:36:21 EDT
*
try {
NodeIterator ni = XPathApi.selectNodeIterator(ele, "//" + tagName);
if (ni != null) {
Element el = (Element)ni.nextNode();
if (el != null) {
Node child = el.getFirstChild();
if (child != null) textVal = child.getNodeValue();
}
}
} catch (TransformerException e) {
e.printStackTrace();
}
*/
// Added on Thu 23 Jun 2011 17:27:10 EDT
if (element != null && element.hasChildNodes()) {
// only elements with child nodes will have any content
if (element.getTagName().equals(tagName)) {
// we found our tag at this element
textVal = element.getFirstChild().getNodeValue();
} else {
// search the tag hierarchy instead
NodeList nl = element.getElementsByTagName(tagName);
for (int i = 0; i < nl.getLength(); i++) {
Element el = (Element) nl.item(i);
if (el != null) {
Node child = el.getFirstChild();
if (child != null) {
textVal = child.getNodeValue();
break; // I assume we want to return the first matched result and not the last as the old code did? -AZ
}
}
}
}
}
return textVal;
}
/**
* @param e
* @return
* @deprecated Do not use this, it is currently unused -AZ
*/
public static boolean hasChildren (Element e) {
// This is weird... why not use element.hasChildNodes() ?? -AZ
if (e == null) return false;
return e.getFirstChild() != null;
}
/**
* Finds an element within and element based on an xpath expression
* NOTE: this will fail if more than one element is matched by the xPathExpression
*
* @param element the XML element to search for elements within
* @param xPathExpression string representing an xpath filter (e.g. /xml/result)
* @return the element found by this xpath expression
* @throws XPathExpressionException if more than one element is found or the expression is invalid or other xpath failure occurs
*/
public static Element getElementByXPath(Element element, String xPathExpression) throws XPathExpressionException {
XPath xPath = XPathFactory.newInstance().newXPath();
Element foundElement = (Element)xPath.evaluate(xPathExpression, element, XPathConstants.NODE);
return foundElement;
}
}