1 /* 2 * This file is part of *** M y C o R e *** 3 * See http://www.mycore.de/ for details. 4 * 5 * MyCoRe is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * MyCoRe is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with MyCoRe. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 package org.mycore.common.xml; 20 21 import org.jdom2.Attribute; 22 import org.jdom2.Document; 23 import org.jdom2.Element; 24 import org.jdom2.Namespace; 25 import org.jdom2.Parent; 26 import org.mycore.common.MCRConstants; 27 28 import java.util.List; 29 30 /** 31 * Builds an absolute XPath expression for a given element or attribute within a JDOM XML structure. 32 * 33 * @author Frank L\u00FCtzenkirchen 34 */ 35 public class MCRXPathBuilder { 36 37 /** 38 * Builds an absolute XPath expression for a given element or attribute within a JDOM XML structure. 39 * For each element that is not the root element, the XPath will also contain a position predicate. 40 * For all namespaces commonly used in MyCoRe, their namespace prefixes will be used. 41 * 42 * @param object a JDOM element or attribute 43 * @return absolute XPath of that object. In case there is a root Document, it will begin with a "/". 44 */ 45 public static String buildXPath(Object object) { 46 if (object instanceof Element) { 47 return buildXPath((Element) object); 48 } else if (object instanceof Attribute) { 49 return buildXPath((Attribute) object); 50 } else { 51 return ""; 52 } 53 } 54 55 /** 56 * Builds an absolute XPath expression for the given attribute within a JDOM XML structure. 57 * For each element that is not the root element, the XPath will also contain a position predicate. 58 * For all namespaces commonly used in MyCoRe, their namespace prefixes will be used. 59 * 60 * @param attribute a JDOM attribute 61 * @return absolute XPath of that attribute. In case there is a root Document, it will begin with a "/". 62 */ 63 public static String buildXPath(Attribute attribute) { 64 String parentXPath = buildXPath(attribute.getParent()); 65 if (!parentXPath.isEmpty()) { 66 parentXPath += "/"; 67 } 68 return parentXPath + "@" + attribute.getQualifiedName(); 69 } 70 71 /** 72 * Builds an absolute XPath expression for the given element within a JDOM XML structure. 73 * For each element that is not the root element, the XPath will also contain a position predicate. 74 * For all namespaces commonly used in MyCoRe, their namespace prefixes will be used. 75 * 76 * @param element a JDOM element 77 * @return absolute XPath of that element. In case there is a root Document, it will begin with a "/". 78 */ 79 public static String buildXPath(Element element) { 80 if (element == null) { 81 return ""; 82 } 83 84 String parentXPath = buildXPath(element.getParent()); 85 if ((!parentXPath.isEmpty()) || (element.getParent() instanceof Document)) { 86 parentXPath += "/"; 87 } 88 return parentXPath + buildChildPath(element); 89 } 90 91 /** 92 * Builds a local XPath fragment as combined namespace prefix, local element name and position predicate 93 */ 94 public static String buildChildPath(Element element) { 95 return getNamespacePrefix(element) + element.getName() + buildPositionPredicate(element); 96 } 97 98 /** 99 * Returns the namespace prefix for this element, followed by a ":", 100 * or the empty string if no namespace prefix known. 101 */ 102 public static String getNamespacePrefix(Element element) { 103 Namespace nsElement = element.getNamespace(); 104 for (Namespace ns : MCRConstants.getStandardNamespaces()) { 105 if (ns.equals(nsElement)) { 106 return ns.getPrefix() + ":"; 107 } 108 } 109 110 String prefix = nsElement.getPrefix(); 111 if ((prefix != null) && !prefix.isEmpty()) { 112 return prefix + ":"; 113 } else { 114 return ""; 115 } 116 } 117 118 private static String buildPositionPredicate(Element element) { 119 Parent parent = element.getParent(); 120 if ((parent instanceof Document) || (parent == null)) { 121 return ""; 122 } 123 124 Element parentElement = (Element) parent; 125 List<Element> siblings = parentElement.getChildren(element.getName(), element.getNamespace()); 126 int pos = siblings.indexOf(element) + 1; 127 128 return "[" + pos + "]"; 129 } 130 }