blob: 675f92b8814ff5363ba6b1d9f935343ae1b11571 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.pivot.xml;
import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.List;
import org.apache.pivot.util.Utils;
/**
* Contains utility methods for working with XML structures.
*/
public final class XML {
/**
* Private constructor for utility class.
*/
private XML() {
}
/**
* Returns the element matching a given path.
*
* @param root The element from which to begin the search.
* @param path A path of the form: <pre> tag[n]/tag[n]/... </pre> The
* bracketed index values are optional and refer to the <i>n</i>th
* occurrence of the given tag name within its parent element. If omitted,
* the path refers to the first occurrence of the named element (i.e. the
* element at index 0).
* @return The matching element, or {@code null} if no such element exists.
*/
public static Element getElement(final Element root, final String path) {
Utils.checkNull(root, "root");
Utils.checkNullOrEmpty(path, "path");
ArrayList<String> pathComponents = new ArrayList<>(path.split("/"));
Element current = root;
for (int i = 0, n = pathComponents.getLength(); i < n; i++) {
String pathComponent = pathComponents.get(i);
String tagName;
int index;
int leadingBracketIndex = pathComponent.indexOf('[');
if (leadingBracketIndex == -1) {
tagName = pathComponent;
index = 0;
} else {
tagName = pathComponent.substring(0, leadingBracketIndex);
int trailingBracketIndex = pathComponent.lastIndexOf(']');
if (trailingBracketIndex == -1) {
throw new IllegalArgumentException("Unterminated index identifier.");
}
index = Integer.parseInt(pathComponent.substring(leadingBracketIndex + 1,
trailingBracketIndex));
}
int j = 0;
int k = 0;
for (Node node : current) {
if (node instanceof Element) {
Element element = (Element) node;
if (element.getName().equals(tagName)) {
if (k == index) {
break;
}
k++;
}
}
j++;
}
if (j < current.getLength()) {
current = (Element) current.get(j);
} else {
current = null;
break;
}
}
return current;
}
/**
* Returns the sub-elements of a descendant of {@code root} whose tag names
* match the given name.
*
* @param root The element from which to begin the search.
* @param path The path to the descendant, relative to {@code root}.
* @param name The tag name to match.
* @return The matching elements, or {@code null} if no such descendant
* exists.
* @see #getElement(Element, String)
* @see Element#getElements(String)
*/
public static List<Element> getElements(final Element root, final String path, final String name) {
Element element = getElement(root, path);
return (element == null) ? null : element.getElements(name);
}
/**
* Returns the text content of a descendant of {@code root}.
*
* @param root The element from which to begin the search.
* @param path The path to the descendant, relative to {@code root}.
* @return The text of the descedant, or {@code null} if no such descendant
* exists.
* @see #getElement(Element, String)
* @see Element#getText()
*/
public static String getText(final Element root, final String path) {
Element element = getElement(root, path);
return (element == null) ? null : element.getText();
}
}