Does anyone know of an existing means of creating an XML hierarchy programatically from an XPath expression?
For example if I have an XML fragment such as:
I know this is a really old thread ... but I have just been trying the same thing and came up with the following regex which is not perfect but I find more generic
/+([\w]+)(\[@([\w]+)='([^']*)'\])?|/@([\w]+)
The string /configuration/appSettings/add[@key='name']/@value
should be parsed to
Found 14 match(es):
start=0, end=14 Group(0) = /configuration Group(1) = configuration Group(2) = null Group(3) = null Group(4) = null Group(5) = null
start=14, end=26 Group(0) = /appSettings Group(1) = appSettings Group(2) = null Group(3) = null Group(4) = null Group(5) = null
start=26, end=43 Group(0) = /add[@key='name'] Group(1) = add Group(2) = [@key='name'] Group(3) = key Group(4) = name Group(5) = null
start=43, end=50 Group(0) = /@value Group(1) = null Group(2) = null Group(3) = null Group(4) = null Group(5) = value
Which means we have
Group(0) = Ignored Group(1) = The element name Group(2) = Ignored Group(3) = Filter attribute name Group(4) = Filter attribute value
Here is a java method which can use the pattern
public static Node createNodeFromXPath(Document doc, String expression) throws XPathExpressionException {
StringBuilder currentPath = new StringBuilder();
Matcher matcher = xpathParserPattern.matcher(expression);
Node currentNode = doc.getFirstChild();
while (matcher.find()) {
String currentXPath = matcher.group(0);
String elementName = matcher.group(1);
String filterName = matcher.group(3);
String filterValue = matcher.group(4);
String attributeName = matcher.group(5);
StringBuilder builder = currentPath.append(currentXPath);
String relativePath = builder.toString();
Node newNode = selectSingleNode(doc, relativePath);
if (newNode == null) {
if (attributeName != null) {
((Element) currentNode).setAttribute(attributeName, "");
newNode = selectSingleNode(doc, relativePath);
} else if (elementName != null) {
Element element = doc.createElement(elementName);
if (filterName != null) {
element.setAttribute(filterName, filterValue);
}
currentNode.appendChild(element);
newNode = element;
} else {
throw new UnsupportedOperationException("The given xPath is not supported " + relativePath);
}
}
currentNode = newNode;
}
if (selectSingleNode(doc, expression) == null) {
throw new IllegalArgumentException("The given xPath cannot be created " + expression);
}
return currentNode;
}