001: /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
002: *
003: * Permission is hereby granted, free of charge, to any person obtaining a copy
004: * of this software and associated documentation files (the "Software"), to deal
005: * in the Software without restriction, including without limitation the rights
006: * to use, copy, modify, merge, publish, distribute, sublicense, and/or
007: * sell copies of the Software, and to permit persons to whom the Software is
008: * furnished to do so, subject to the following conditions:
009: *
010: * The above copyright notice and this permission notice shall be included in
011: * all copies or substantial portions of the Software.
012: *
013: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
014: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
015: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
016: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
017: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
018: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
019: * IN THE SOFTWARE. */
020:
021: package org.kxml2.kdom;
022:
023: import java.io.*;
024: import java.util.*;
025:
026: import org.xmlpull.v1.*;
027:
028: /**
029: * In order to create an element, please use the createElement method
030: * instead of invoking the constructor directly. The right place to
031: * add user defined initialization code is the init method. */
032:
033: public class Element extends Node {
034:
035: protected String namespace;
036: protected String name;
037: protected Vector attributes;
038: protected Node parent;
039: protected Vector prefixes;
040:
041: public Element() {
042: }
043:
044: /**
045: * called when all properties are set, but before children
046: * are parsed. Please do not use setParent for initialization
047: * code any longer. */
048:
049: public void init() {
050: }
051:
052: /**
053: * removes all children and attributes */
054:
055: public void clear() {
056: attributes = null;
057: children = null;
058: }
059:
060: /**
061: * Forwards creation request to parent if any, otherwise
062: * calls super.createElement. */
063:
064: public Element createElement(String namespace, String name) {
065:
066: return (this .parent == null) ? super .createElement(namespace,
067: name) : this .parent.createElement(namespace, name);
068: }
069:
070: /**
071: * Returns the number of attributes of this element. */
072:
073: public int getAttributeCount() {
074: return attributes == null ? 0 : attributes.size();
075: }
076:
077: public String getAttributeNamespace(int index) {
078: return ((String[]) attributes.elementAt(index))[0];
079: }
080:
081: /* public String getAttributePrefix (int index) {
082: return ((String []) attributes.elementAt (index)) [1];
083: }*/
084:
085: public String getAttributeName(int index) {
086: return ((String[]) attributes.elementAt(index))[1];
087: }
088:
089: public String getAttributeValue(int index) {
090: return ((String[]) attributes.elementAt(index))[2];
091: }
092:
093: public String getAttributeValue(String namespace, String name) {
094: for (int i = 0; i < getAttributeCount(); i++) {
095: if (name.equals(getAttributeName(i))
096: && (namespace == null || namespace
097: .equals(getAttributeNamespace(i)))) {
098: return getAttributeValue(i);
099: }
100: }
101: return null;
102: }
103:
104: /**
105: * Returns the root node, determined by ascending to the
106: * all parents un of the root element. */
107:
108: public Node getRoot() {
109:
110: Element current = this ;
111:
112: while (current.parent != null) {
113: if (!(current.parent instanceof Element))
114: return current.parent;
115: current = (Element) current.parent;
116: }
117:
118: return current;
119: }
120:
121: /**
122: * returns the (local) name of the element */
123:
124: public String getName() {
125: return name;
126: }
127:
128: /**
129: * returns the namespace of the element */
130:
131: public String getNamespace() {
132: return namespace;
133: }
134:
135: /**
136: * returns the namespace for the given prefix */
137:
138: public String getNamespaceUri(String prefix) {
139: int cnt = getNamespaceCount();
140: for (int i = 0; i < cnt; i++) {
141: if (prefix == getNamespacePrefix(i)
142: || (prefix != null && prefix
143: .equals(getNamespacePrefix(i))))
144: return getNamespaceUri(i);
145: }
146: return parent instanceof Element ? ((Element) parent)
147: .getNamespaceUri(prefix) : null;
148: }
149:
150: /**
151: * returns the number of declared namespaces, NOT including
152: * parent elements */
153:
154: public int getNamespaceCount() {
155: return (prefixes == null ? 0 : prefixes.size());
156: }
157:
158: public String getNamespacePrefix(int i) {
159: return ((String[]) prefixes.elementAt(i))[0];
160: }
161:
162: public String getNamespaceUri(int i) {
163: return ((String[]) prefixes.elementAt(i))[1];
164: }
165:
166: /**
167: * Returns the parent node of this element */
168:
169: public Node getParent() {
170: return parent;
171: }
172:
173: /*
174: * Returns the parent element if available, null otherwise
175:
176: public Element getParentElement() {
177: return (parent instanceof Element)
178: ? ((Element) parent)
179: : null;
180: }
181: */
182:
183: /**
184: * Builds the child elements from the given Parser. By overwriting
185: * parse, an element can take complete control over parsing its
186: * subtree. */
187:
188: public void parse(XmlPullParser parser) throws IOException,
189: XmlPullParserException {
190:
191: for (int i = parser.getNamespaceCount(parser.getDepth() - 1); i < parser
192: .getNamespaceCount(parser.getDepth()); i++) {
193: setPrefix(parser.getNamespacePrefix(i), parser
194: .getNamespaceUri(i));
195: }
196:
197: for (int i = 0; i < parser.getAttributeCount(); i++)
198: setAttribute(parser.getAttributeNamespace(i),
199: // parser.getAttributePrefix (i),
200: parser.getAttributeName(i), parser
201: .getAttributeValue(i));
202:
203: // if (prefixMap == null) throw new RuntimeException ("!!");
204:
205: init();
206:
207: if (parser.isEmptyElementTag())
208: parser.nextToken();
209: else {
210: parser.nextToken();
211: super .parse(parser);
212:
213: if (getChildCount() == 0)
214: addChild(IGNORABLE_WHITESPACE, "");
215: }
216:
217: parser
218: .require(XmlPullParser.END_TAG, getNamespace(),
219: getName());
220:
221: parser.nextToken();
222: }
223:
224: /**
225: * Sets the given attribute; a value of null removes the attribute */
226:
227: public void setAttribute(String namespace, String name, String value) {
228: if (attributes == null)
229: attributes = new Vector();
230:
231: if (namespace == null)
232: namespace = "";
233:
234: for (int i = attributes.size() - 1; i >= 0; i--) {
235: String[] attribut = (String[]) attributes.elementAt(i);
236: if (attribut[0].equals(namespace)
237: && attribut[1].equals(name)) {
238:
239: if (value == null) {
240: attributes.removeElementAt(i);
241: } else {
242: attribut[2] = value;
243: }
244: return;
245: }
246: }
247:
248: attributes.addElement(new String[] { namespace, name, value });
249: }
250:
251: /**
252: * Sets the given prefix; a namespace value of null removess the
253: * prefix */
254:
255: public void setPrefix(String prefix, String namespace) {
256: if (prefixes == null)
257: prefixes = new Vector();
258: prefixes.addElement(new String[] { prefix, namespace });
259: }
260:
261: /**
262: * sets the name of the element */
263:
264: public void setName(String name) {
265: this .name = name;
266: }
267:
268: /**
269: * sets the namespace of the element. Please note: For no
270: * namespace, please use Xml.NO_NAMESPACE, null is not a legal
271: * value. Currently, null is converted to Xml.NO_NAMESPACE, but
272: * future versions may throw an exception. */
273:
274: public void setNamespace(String namespace) {
275: if (namespace == null)
276: throw new NullPointerException(
277: "Use \"\" for empty namespace");
278: this .namespace = namespace;
279: }
280:
281: /**
282: * Sets the Parent of this element. Automatically called from the
283: * add method. Please use with care, you can simply
284: * create inconsitencies in the document tree structure using
285: * this method! */
286:
287: protected void setParent(Node parent) {
288: this .parent = parent;
289: }
290:
291: /**
292: * Writes this element and all children to the given XmlWriter. */
293:
294: public void write(XmlSerializer writer) throws IOException {
295:
296: if (prefixes != null) {
297: for (int i = 0; i < prefixes.size(); i++) {
298: writer.setPrefix(getNamespacePrefix(i),
299: getNamespaceUri(i));
300: }
301: }
302:
303: writer.startTag(getNamespace(), getName());
304:
305: int len = getAttributeCount();
306:
307: for (int i = 0; i < len; i++) {
308: writer.attribute(getAttributeNamespace(i),
309: getAttributeName(i), getAttributeValue(i));
310: }
311:
312: writeChildren(writer);
313:
314: writer.endTag(getNamespace(), getName());
315: }
316: }
|