package org.crosswire.xml;
/**
* Copyright (c) 2001 CrossWire Bible Society.
* Distributable under the terms of the GNU GPL V2.
*/
import java.io.InputStream;
import java.io.OutputStream;
import org.w3c.dom.Node;
/** A basic utility for manipulating a block of XML data.
* This utility class can manipulate arbitrary tags, values, and subblocks
* of an XML block. It is meant to be extended, with the subclass providing
* setters and getters for tags, values, and subblocks so as to solidify
* the XML scheme.
*
* @author Troy A. Griffitts
* @version $Id: XMLBlock.java,v 1.24.2.9 2001/03/10 00:00:35 troy Exp $
*/
public class XMLBlock extends XMLTag implements org.crosswire.webtools.CustomXMLDoc {
/** A static method to construct and return an XMLBlock by asking a
* DOM Parser to parse a String of XML and assign this XMLBlock's root
* to the root of the parsed tree.
* @param xml the String of XML to parse.
* @return the created XMLBlock.
* @exception XMLParseException if the string is not well formed XML
*/
public static XMLBlock getRoot(String xml) throws XMLParseException {
return LocalXMLProvider.getRoot(xml);
}
/** A static method to construct and return an XMLBlock by asking a
* DOM Parser to parse a String of XML. This method does not explicitly
* throw an exception and should be used only for an XML string that is
* known to be well formed.
* @param xml the String of XML to parse and create an XMLBlock from.
* @return the created XMLBlock.
*/
public static XMLBlock createXMLBlock(String xml) {
try {
return LocalXMLProvider.getRoot(xml);
} catch(Exception exp) {
throw new RuntimeException(exp.toString());
}
}
public static XMLBlock loadXMLBlock(InputStream in) {
try {
return new XMLBlock(LocalXMLProvider.streamToNode(in));
} catch(Exception exp) {
throw new RuntimeException(exp.toString());
}
}
public void save(OutputStream out) {
try {
LocalXMLProvider.nodeToStream(getNode(), out);
} catch(Exception exp) {
throw new RuntimeException(exp.toString());
}
}
public XMLBlock(XMLProvider p, XMLResolver r) {
super(p, r);
}
/** Construct an XMLBlock with a W3C Node object as it's root.
* @param root the W3C Node object to designate as this block's 'root'.
*/
public XMLBlock(Node root) {
super(root);
}
/** Construct an XMLBlock obtaining its identity from another XMLBlock or
* subclass. The new object will read and modify the same data as the
* object passed to it.
* @param other the other object from which to grab identity.
*/
public XMLBlock(XMLTag other) {
super(other);
}
/** Construct an XMLBlock by asking a DOM Parser to parse a String of XML
* and assign this XMLBlock's root to the root of the parsed tree.
* @param xml the String of XML to parse.
* @exception XMLParseException if the string is not well formed XML
*/
public XMLBlock(String xml) throws XMLParseException {
this(XMLBlock.getRoot(xml));
}
/** Gets a value from a tag block (eg. <TAG>VALUE</TAG>) that is a child
* of this XMLBlock.
* @param key the tag name to find and for which to retrieve the value.
* @return VALUE text for the tag.
*/
public String getValue(String key) {
return provider.getValue(key);
}
/** Sets a value for a tag block (eg. <TAG>VALUE</TAG>) that is a child
* of this XMLBlock. The tag block will be created if it does not exist.
* @param key the tag name to find/create and for which to set the value.
* @param value the value text to set for the tag block.
* @return the XMLDataElement that was set/created.
*/
public XMLDataElement setValue(String key, String value) {
return resolver.setValue(key, value);
}
/** Creates and sets a value for a tag block (eg. <TAG>VALUE</TAG>) as a
* child of this XMLBlock. The tag block will be created regardless if
* another tag block with the same key value already exists.
* @param key the tag name to create and for which to set the value.
* @param value the value text to set for the tag block.
* @return the XMLDataElement that was created.
*/
public XMLDataElement createValue(String key, String value) {
return resolver.createValue(key, value);
}
public XMLDataElement getElement(String key) {
return provider.getElement(key);
}
/** Gets all <TAG>VALUE</TAG> type elements that are immediate children
* of this XMLBlock.
* @return array of XMLDataElement objects.
*/
public XMLDataElement [] getElements() {
return provider.getElements();
}
/** Gets all <TAG>VALUE</TAG> type elements that are immediate children
* of this XMLBlock.
* @return array of XMLDataElement objects.
*/
public XMLDataElement [] getElements(String key) {
return provider.getElements(key);
}
/** Copies an XMLBlock to this document as a child of this XMLBlock.
* @param newBlk the block to import.
* @return the new XMLBlock child of this XMLBlock.
*/
public XMLBlock addBlock(XMLBlock newBlk) {
return resolver.addBlock(newBlk);
}
/** Creates a new block as a child of this XMLBlock. The block will be
* created regardless if another block with the same key value already
* exists.
* @param key the tag name to give the newly created block.
* @return the XMLBlock that was created.
*/
public XMLBlock createBlock(String key) {
return resolver.createBlock(key);
}
/** Removes a child from this XMLBlock. All XMLObjects extend from XMLTag,
* so sending any XMLObject previously retrieved from this block will
* remove it from this block.
* @param tag any XMLObject that is a child of this XMLBlock.
*/
public void removeChild(XMLTag tag) {
resolver.removeChild(tag);
}
/** Gets all the children of this XMLBlock.
* @return array of XMLTag objects.
*/
public XMLTag [] getChildren() {
return provider.getChildren();
}
/** Gets all block type elements that are immediate children of this
* XMLBlock.
* @return array of XMLBlock objects.
*/
public XMLBlock [] getBlocks() {
return provider.getBlocks();
}
/** Gets all block type elements that are immediate children of this
* XMLBlock and that have a specified tag name.
* @param key the tag name for which to find corresponding child XMLBlock
* objects.
* @return array of XMLBlock objects.
*/
public XMLBlock [] getBlocks(String key) {
return provider.getBlocks(key);
}
public XMLBlock [] getBlocks(String key, Class clas) {
return provider.getBlocks(key, clas);
}
/** Gets all block type elements that are immediate children of this
* XMLBlock and that have a specified tag name and attribute value pair.
* @param key the tag name for which to find corresponding child XMLBlock
* objects.
* @param attr1 the attribute on which to filter.
* @param att1Val the attribute value for which to filter.
* @return array of XMLBlock objects.
*/
public XMLBlock [] getBlocks(String key, String attr1, String att1Val) {
return provider.getBlocks(key, attr1, att1Val);
}
public XMLBlock [] getBlocks(String key, String attr1, String att1Val, Class clas) {
return provider.getBlocks(key, attr1, att1Val, clas);
}
/** Gets all block type elements that are immediate children of this
* XMLBlock and that have a specified tag name and 2 attribute value pairs.
* @param key the tag name for which to find corresponding child XMLBlock
* objects.
* @param attr1 the first attribute on which to filter.
* @param att1Val the first attribute value for which to filter.
* @param attr2 the second attribute on which to filter.
* @param att2Val the second attribute value for which to filter.
* @return array of XMLBlock objects.
*/
public XMLBlock [] getBlocks(String key, String attr1, String att1Val,
String attr2, String att2Val) {
return provider.getBlocks(key, attr1, att1Val, attr2, att2Val);
}
public XMLBlock [] getBlocks(String key, String attr1, String att1Val,
String attr2, String att2Val, Class clas) {
return provider.getBlocks(key, attr1, att1Val, attr2, att2Val, clas);
}
/** Gets the first block type element that is an immediate child of this
* XMLBlock and that has a specified tag name.
* @param key the tag name for which to find corresponding child XMLBlock
* objects.
* @return the first XMLBlock that meets the criteria, otherwise null.
*/
public XMLBlock getBlock(String key) {
return provider.getBlock(key);
}
/** Gets the first block type element that is an immediate child of this
* XMLBlock and that has a specified tag name and attribute value pair.
* @param key the tag name for which to find corresponding child XMLBlock
* objects.
* @param attr1 the attribute on which to filter.
* @param att1Val the attribute value for which to filter.
* @return the first XMLBlock that meets the criteria, otherwise null.
*/
public XMLBlock getBlock(String key, String attr1, String att1Val) {
return provider.getBlock(key, attr1, att1Val);
}
/** Gets the first block type element that is an immediate child of this
* XMLBlock and that has a specified tag name and 2 attribute value pairs.
* @param key the tag name for which to find corresponding child XMLBlock
* objects.
* @param attr1 the first attribute on which to filter.
* @param att1Val the first attribute value for which to filter.
* @param attr2 the second attribute on which to filter.
* @param att2Val the second attribute value for which to filter.
* @return array of XMLBlock objects
*/
public XMLBlock getBlock(String key, String attr1, String att1Val,
String attr2, String att2Val) {
return provider.getBlock(key, attr1, att1Val, attr2, att2Val);
}
/** Filters an array of XMLBlocks by an attribute, value pair
* @param attr the attribute on which to filter.
* @param attVal the attribute value for which to filter.
* @return the new XMLBlock array filtered by the attribute, value pair.
*/
public XMLBlock [] filterBlocks(XMLBlock[]superset, String attr, String attVal) {
return provider.filterBlocks(superset, attr, attVal);
}
/** Retrieves the String representation of this XMLBlock and children.
* @return the String representation of this XMLBlock and children.
*/
public String toString() {
return provider.toString();
}
public String toXML(int detailLevel) {
return toString();
}
public String formattedString() {
// cool way
StringBuffer retVal = new StringBuffer(super.toString()+"\n");
XMLBlock [] blocks = getBlocks();
for (int i = 0; i < blocks.length; i++)
retVal.append(blocks[i].formattedString());
XMLDataElement [] elements = getElements();
for (int i = 0; i < elements.length; i++)
retVal.append(elements[i].toString());
retVal.append(""+getName()+">\n");
return retVal.toString();
}
/** A utility function for subclasses to provide common 'property'.
* functionality for an XMLBlock XMLDataElement.
*
*
*
* eg.
*
* String getSKU() { return stdProp("SKU"); }
*
*
*
* @param key the key name of the property.
* @return the value of the property.
*/
protected String stdProp(String key) {
String val = getValue(key);
/* don't assign default "" values
if (val == null) {
createValue(key, "");
val = "";
}
*/
return val;
}
/** A utility function for subclasses to provide common 'property'
* functionality for an XMLBlock XMLDataElement.
*
*
*
* eg.
*
* void setSKU(String value) { stdProp("SKU", value); }
*
*
*
* @param key the key name of the property.
* @param value the value to which to set the property.
*/
protected void stdProp(String key, String value) {
setValue(key, value);
}
public static void main(String[] args) {
String modListURL = "http://www.crosswire.org/study/examples/booklistxml.jsp";
StringBuffer result = org.crosswire.utils.HTTPUtils.postURL(modListURL, null);
XMLBlock modules = XMLBlock.createXMLBlock(result.toString());
// for (XMLBlock module : modules.getBlocks("module", "category", "Biblical Texts")) {
System.out.println("Count: "+modules.getBlocks("module").length);
for (XMLDataElement module : modules.getElements("module")) {
System.out.println("