Skip to content

Instantly share code, notes, and snippets.

@tomvit
Last active July 30, 2017 20:37
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomvit/1428469 to your computer and use it in GitHub Desktop.
Save tomvit/1428469 to your computer and use it in GitHub Desktop.
Create elements and/or an attribute or a text node along a path in xml.
/**
* Create elements and/or an attribute or a text node along a path in xml.
* Examples: let root be a xml element
* <foo/>
*
* To create a sub-element bar with an attribute id set to a value '5':
* Node n = createXmlPath(root, "/foo/bar/@id", "5");
*
* To create a sub-element bar with a text content set to a value '7':
* Node n = createXmlPath(root, "/foo/bar/text()", "7);
*
* To create an empty sub-element bar
* Node n = createXmlPath(root, "/foo/bar", null);
*
* @param root element under which new elements and/or text or attribute nodes will be created.
* @param xpath xpath expression, must be in a form as examples show.
* @param nodeValue Value for a text node or an attribute if present at the end of the path.
* @return The last element on the path.
* @throws XPathExpressionException
*/
public static Node createXmlPath(Element root, String xpath, String nodeValue) throws XPathExpressionException {
// try to select nodes according to xpath
XPath xp = XPathFactory.newInstance().newXPath();
NodeList ns = (NodeList) xp.evaluate(xpath, root, XPathConstants.NODESET);
Node n = ns.getLength() > 0 ? ns.item(0) : null;
// create elements if the expression returns zero nodes
if (n == null) {
// parse the expression - get the last element from the xpath
String pattern = "(.*)/([A-Za-z0-9\\-_\\(\\)@]+)$";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(xpath);
if (m.matches()) {
// recursive call - create the elements on the path that does not include the last element
Node pn = createXmlPath(root, m.group(1), null);
// if the last element is a text node,
// create the text node and set its value to nodeValue
if (m.group(2).equals("text()")) {
n = root.getOwnerDocument().createTextNode(nodeValue != null ? nodeValue : "__");
pn.appendChild(n);
n = pn;
} else
// if the last element is attribute,
// create the attribute and set its value to nodeValue
if (m.group(2).matches("@[A-Za-z\\-_0-9]+")) {
Node a = root.getOwnerDocument().createAttribute(m.group(2).substring(1));
a.setNodeValue(nodeValue != null ? nodeValue : "__");
pn.getAttributes().setNamedItem(a);
n = pn;
} else {
// otherwise create normal element
n = root.getOwnerDocument().createElement(m.group(2));
pn.appendChild(n);
}
} else
throw new XPathExpressionException("XPath expression must match the pattern '" + pattern + "'!");
}
return n;
}
@ysimhadri
Copy link

Hi,

I was trying to get this to work but was out of luck.Is there a working sample.Any inputs would be of great help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment