package com.purpletech.xml; import com.purpletech.util.*; import java.util.*; import java.io.*; import org.w3c.dom.*; import org.xbeans.*; // todo: make changes propagate to DOM node /** * An EntryList that can parse a DOM node to set its values.

* * Contiguous text nodes in the tree get concatenated, and stored as an * entry named "#text". It has complicated rules for parsing text * nodes, but they do what you'd expect them to do in most cases.

* * Supports XBeans events. **/ public class XMLEntryList extends EntryList implements DOMListener, DOMSource, XMLPrinter { static protected XMLEntryListFactory defaultfactory = new XMLEntryListFactory(); protected List attributes = new ArrayList(); protected String listName; protected XMLEntryListFactory factory = defaultfactory; protected Node node; public XMLEntryList() {} public XMLEntryList(Node node) throws XMLException { this.node = node; setListName(node.getNodeName()); parseNode(); } public XMLEntryList(String listName, XMLEntryListFactory factory) { setListName(listName); setFactory(factory); } public XMLEntryList(String listName, XMLEntryListFactory factory, Node node) throws XMLException { setListName(listName); setFactory(factory); this.node = node; parseNode(); } public Object get(Object key) { if (key.equals("")) key = "#text"; return super.get(key); } protected void parseNode() throws XMLException { if (factory.parse(node, this) != this) { throw new XMLException("inappropriate node"); } } public void setFactory(XMLEntryListFactory factory) { if (factory != null) this.factory = factory; } protected XMLEntryListFactory getFactory() { return factory; } public void setAttribute(String attname) { if (!attributes.contains(attname)) attributes.add(attname); } public void setListName(String listName) { this.listName = listName; } public String getListName() { return listName; } /** does NOT parse -- must call parseNode() immediately **/ public void setNode(Node node) { this.node = node; } /** * returns this, so you can say "new XMLEntryList().parseNode(node)" **/ public XMLEntryList parseNode(Node node) throws XMLException { this.node = node; parseNode(); return this; } public Node getNode() { return node; } public void printXml(PrintStream out) { printXML(out); } public void printXML(PrintStream out) { PrintWriter w = new PrintWriter(out); printXml(w,0); w.flush(); } public void printXml(PrintWriter out, int indent) { printXML(out,indent); } /** * If it has a name, then it'll print itself as an XML element, * including tag name and attributes. If its name is null, then it * just prints its elements. **/ public void printXML(PrintWriter out, int indent) { Iterator i; // print tag if (listName != null) { if (indent > 0) { out.println(); Utils.printIndent(out, indent); } printOpenTag(out, listName, attributes); } if (this.get("#text") == null) { // has no text, so indent prettily indent += 2; printElements(out, indent); indent -= 2; out.println(); Utils.printIndent(out, indent); } else { // has some text, so jam it onto one line printElements(out,0); } if (listName != null) printCloseTag(out, listName); } public void printElements(PrintWriter out, int indent) { // print elements Iterator i = iterator(); while (i.hasNext()) { Map.Entry e = (Map.Entry)i.next(); printElement(out, indent, e); } } // printElements protected void printElement(PrintWriter out, int indent, Map.Entry entry) { if (entry.getValue() instanceof XMLPrinter) { ((XMLPrinter)entry.getValue()).printXML(out, indent); } else if (listName == null || !attributes.contains(entry.getKey())) { if (entry.getValue() != null) // skip null values ??? { if (indent > 0 ) { out.println(); Utils.printIndent(out, indent); } String tag = (String)entry.getKey(); printOpenTag(out, tag, null); // if (entry.getValue() != null) out.print(fix(entry.getValue().toString())); printCloseTag(out, tag); } } } // printElement protected void printOpenTag(PrintWriter out, String tag, List attributes) { boolean isText = (tag.equals("#text")); boolean isComment = (tag.equals("#comment")); if (isText) { } else if (isComment) { out.print(""); } else { out.print(""); } } /** * return a single string representing all sub-elements, including * tags **/ public String flatten() { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); printElements(pw, 0); pw.close(); return sw.toString(); } /** * Squoosh all text children. Turns strings of all-whitespace * nodes into nothing. That is,

     * "#text" = ""
     * "b" = [some other object]
     * "#text" = ""
     * "#text" = "yo mama"
     * "#text" = ""
     * 
turns into
     * "b" = [some other object]
     * "#text" = "yo mama"
     * 
**/ public void squoosh() { String s = ""; int i = 0; // jdk1.2 lets us reuse i while (i