001: /*
002: * JFolder, Copyright 2001-2006 Gary Steinmetz
003: *
004: * Distributable under LGPL license.
005: * See terms of license at gnu.org.
006: */
007:
008: package org.jfolder.common.utils.xml;
009:
010: //base classes
011: import java.util.ArrayList;
012: import java.util.StringTokenizer;
013: import org.w3c.dom.Attr;
014: import org.w3c.dom.Document;
015: import org.w3c.dom.Element;
016: import org.w3c.dom.Node;
017: import org.w3c.dom.NodeList;
018:
019: //project specific classes
020: import org.jfolder.common.UnexpectedSystemException;
021:
022: //other classes
023:
024: public final class LinearXPathHelper {
025:
026: private LinearXPathHelper() {
027: }
028:
029: public final static Element getXPathElement(Document inDocument,
030: LinearXPath inXPath) {
031:
032: Element outValue = null;
033:
034: ArrayList xpath = identifyElementFromXPathSet(inXPath);
035:
036: if (xpath != null) {
037: outValue = getXPathElement(inDocument, xpath);
038: }
039:
040: return outValue;
041: }
042:
043: public final static String getElementAttribute(Document inDocument,
044: LinearXPath inXPath, String inAttrName) {
045:
046: //MiscHelper.println("Get element from attribute = " + inXPath);
047:
048: String outValue = null;
049:
050: Element element = getXPathElement(inDocument, inXPath);
051:
052: if (element != null) {
053: Attr attr = element.getAttributeNode(inAttrName);
054: if (attr != null) {
055: outValue = attr.getValue();
056: }
057: }
058:
059: return outValue;
060: }
061:
062: public final static int getElementSubCount(Document inDocument,
063: LinearXPath inXPath, String inSubElementName) {
064:
065: int outValue = 0;
066:
067: Element parentElement = getXPathElement(inDocument, inXPath);
068:
069: NodeList nl = parentElement.getChildNodes();
070:
071: for (int i = 0; i < nl.getLength(); i++) {
072: Node nextNode = nl.item(i);
073: if (nextNode instanceof Element
074: && nextNode.getNodeName().equals(inSubElementName)) {
075:
076: outValue++;
077: }
078: }
079:
080: return outValue;
081: }
082:
083: private final static Element getXPathElement(Document inDocument,
084: ArrayList inXPath) {
085:
086: Element outValue = null;
087:
088: String errorMess = isXPathValid(inXPath);
089:
090: if (errorMess != null) {
091: throw new UnexpectedSystemException(errorMess);
092: }
093:
094: NodeList nl = inDocument.getChildNodes();
095:
096: topLevel: for (int i = 0; i < inXPath.size(); i++) {
097:
098: XPathElementTuple xpet = (XPathElementTuple) inXPath.get(i);
099:
100: String elementName = xpet.getName();
101: int elementCount = xpet.getIndex();
102:
103: //MiscHelper.println("NextElement = " + elementName);
104: //MiscHelper.println("NextElement(index) = " + elementCount);
105:
106: for (int j = 0; j < nl.getLength(); j++) {
107:
108: Node nextNode = nl.item(j);
109: if (nextNode instanceof Element) {
110: Element nextElement = (Element) nextNode;
111: String nextElementName = nextElement.getTagName();
112: //MiscHelper.println("-aElement = " + nextElementName);
113: if (elementName.equals(nextElementName)) {
114: elementCount--;
115: //MiscHelper.println("-NextElement(i) = "
116: //+ elementCount);
117: if (elementCount == 0) {
118: if (i == (inXPath.size() - 1)) {
119: outValue = nextElement;
120: } else {
121: nl = nextElement.getChildNodes();
122: continue topLevel;
123: }
124: }
125: }
126: }
127: }
128:
129: break;
130: }
131:
132: return outValue;
133: }
134:
135: private final static String isXPathValid(LinearXPath inXPath) {
136: return isXPathValid(identifyElementFromXPathSet(inXPath));
137: }
138:
139: private final static String isXPathValid(ArrayList inXPath) {
140:
141: String outValue = null;
142:
143: if (inXPath != null) {
144:
145: for (int i = 0; i < inXPath.size(); i++) {
146: Object o = inXPath.get(i);
147: String errorMess = null;
148:
149: if (o == null) {
150: errorMess = "XPath malformed after (" + (i + 1)
151: + ") '/'";
152: } else if (!(o instanceof XPathElementTuple)) {
153: errorMess = "XPath corrupt";
154: }
155:
156: if (errorMess != null) {
157: if (outValue != null) {
158: outValue += ";" + errorMess;
159: } else {
160: outValue = errorMess;
161: }
162: }
163: }
164:
165: if (inXPath.size() == 0) {
166: String errorMess = "XPath does not begin with '/'";
167: if (outValue != null) {
168: outValue += ";" + errorMess;
169: } else {
170: outValue = errorMess;
171: }
172: }
173: } else {
174: outValue = "No XPath specified";
175: }
176:
177: return outValue;
178: }
179:
180: private final static ArrayList identifyElementFromXPathSet(
181: LinearXPath inPath) {
182:
183: ArrayList outValue = new ArrayList();
184:
185: String xpath = null;
186: if (inPath != null) {
187: xpath = inPath.toString();
188: }
189:
190: if (xpath != null && xpath.length() > 0
191: && xpath.charAt(0) == '/') {
192:
193: StringTokenizer st = new StringTokenizer(
194: xpath.substring(1), "/");
195:
196: while (st.hasMoreTokens()) {
197: String nextToken = st.nextToken();
198: XPathElementTuple xpet = createElementFromXPath(nextToken);
199: outValue.add(xpet);
200: }
201: }
202:
203: return outValue;
204: }
205:
206: private final static XPathElementTuple createElementFromXPath(
207: String inName) {
208:
209: //MiscHelper.println("xpath portion = " + inName);
210:
211: XPathElementTuple outValue = null;
212:
213: if (inName != null && inName.length() > 0) {
214: char endBracket = inName.charAt(inName.length() - 1);
215: int bracketIndex = inName.indexOf('[');
216:
217: if (bracketIndex > -1 && endBracket == ']') {
218: String name = inName.substring(0, bracketIndex);
219: String index = inName.substring(bracketIndex + 1,
220: inName.length() - 1);
221:
222: //MiscHelper.println("name = " + name);
223: //MiscHelper.println("index = " + index);
224:
225: if (name.length() > 0 && index.length() > 0) {
226:
227: boolean error = false;
228:
229: for (int i = 0; i < name.length(); i++) {
230: char nextChar = name.charAt(i);
231: if ((nextChar >= 'a' && nextChar <= 'z')
232: || (nextChar >= 'A' && nextChar <= 'Z')
233: || (i > 0 && nextChar >= '0' && nextChar <= '9')
234: || (i > 0 && nextChar == '-')) {
235: } else {
236: error = true;
237: }
238: }
239:
240: for (int i = 0; i < index.length(); i++) {
241: char nextChar = index.charAt(i);
242: if (nextChar >= '0' && nextChar <= '9') {
243: } else {
244: error = true;
245: }
246: }
247:
248: if (!error) {
249: int pIndex = Integer.parseInt(index);
250:
251: if (pIndex > 0) {
252: outValue = new XPathElementTuple(name,
253: pIndex);
254: }
255: }
256: }
257: }
258: }
259:
260: return outValue;
261: }
262: }
|