Java Code Examples for org.w3c.dom.Node.TEXT_NODE

The following are Jave code examples for showing how to use TEXT_NODE of the org.w3c.dom.Node class. You can vote up the examples you like. Your votes will be used in our system to get more good examples.
+ Save this method
Example 1
Project: Reer   File: PomDomParser.java   View Source Code Vote up 6 votes
public static String getTextContent(Element element) {
    StringBuilder result = new StringBuilder();

    NodeList childNodes = element.getChildNodes();
    for (int i = 0; i < childNodes.getLength(); i++) {
        Node child = childNodes.item(i);

        switch (child.getNodeType()) {
            case Node.CDATA_SECTION_NODE:
            case Node.TEXT_NODE:
                result.append(child.getNodeValue());
                break;
            default:
                break;
        }
    }

    return result.toString();
}
 
Example 2
Project: parabuild-ci   File: DwrNamespaceHandler.java   View Source Code Vote up 6 votes
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
    BeanDefinitionRegistry registry = parserContext.getRegistry();
    BeanDefinition config = registerSpringConfiguratorIfNecessary(registry);

    StringBuffer sigtext = new StringBuffer();
    NodeList children = node.getChildNodes();
    for (int i = 0; i < children.getLength(); i++)
    {
        Node child = children.item(i);
        if (child.getNodeType() != Node.TEXT_NODE && child.getNodeType() != Node.CDATA_SECTION_NODE)
        {
            log.warn("Ignoring illegal node type: " + child.getNodeType());
            continue;
        }
        sigtext.append(child.getNodeValue());
    }

    config.getPropertyValues().addPropertyValue("signatures", sigtext.toString());

    return definition;
}
 
Example 3
Project: convertigo-engine   File: XMLUtils.java   View Source Code Vote up 6 votes
public static String getNormalizedText(Node node) {
	String res = "";
	if (node.hasChildNodes()) {
		NodeList nl = node.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			if (nl.item(i).getNodeType() == Node.TEXT_NODE) {
				res += nl.item(i).getNodeValue();
			} else {
				// ignore <SCRIPT> nodes ...
				if (!nl.item(i).getNodeName().equalsIgnoreCase("script"))
					res += getNormalizedText(nl.item(i));
			}
		}
	}
	return res;
}
 
Example 4
Project: openjdk-jdk10   File: TextImpl.java   View Source Code Vote up 6 votes
/**
 * Check if an EntityReference node has Text Only child nodes
 *
 * @param node
 * @return true - Contains text only children
 */
private boolean hasTextOnlyChildren(Node node) {

    Node child = node;

    if (child == null) {
        return false;
    }

    child = child.getFirstChild();
    while (child != null) {
        int type = child.getNodeType();

        if (type == Node.ENTITY_REFERENCE_NODE) {
            return hasTextOnlyChildren(child);
        }
        else if (type != Node.TEXT_NODE
                && type != Node.CDATA_SECTION_NODE
                && type != Node.ENTITY_REFERENCE_NODE) {
            return false;
        }
        child = child.getNextSibling();
    }
    return true;
}
 
Example 5
Project: Java-APIs   File: Synonym.java   View Source Code Vote up 5 votes
protected Synonym(Element element) {
	logger.debug("Constructor - entry");

	NodeList nodeList = element.getChildNodes();
	for (int n = 0; n < nodeList.getLength(); n++) {
		Node node = nodeList.item(n);
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			Element childElement = (Element) node;
		    if ("RELATION_METADATA".equals(childElement.getNodeName())) {
		    	setRelationMetadata(new RelationMetadata(childElement));
		    } else {
		    	logger.trace("Unrecognized child node: '" + childElement.getNodeName() + "'");
		    }
		} else if (node.getNodeType() == Node.TEXT_NODE) {
			this.setValue(node.getNodeValue());
		}
	}

	NamedNodeMap namedNodeMap = element.getAttributes();
	if (namedNodeMap != null) {
		for (int a = 0; a < namedNodeMap.getLength(); a++) {
			Attr attributeNode = (Attr) namedNodeMap.item(a);
			if ("ID".equals(attributeNode.getName())) {
				setId(attributeNode.getValue());
			} else {
				logger.trace("Unrecognized attribute: '" + attributeNode.getName() + "' (" + this.getClass().getName() + ")");
			}
		}
	}


	logger.debug("Constructor - exit");
}
 
Example 6
Project: OpenJSharp   File: TransformBase64Decode.java   View Source Code Vote up 5 votes
void traverseElement(org.w3c.dom.Element node, StringBuilder sb) {
    Node sibling = node.getFirstChild();
    while (sibling != null) {
        switch (sibling.getNodeType()) {
        case Node.ELEMENT_NODE:
            traverseElement((Element)sibling, sb);
            break;
        case Node.TEXT_NODE:
            sb.append(((Text)sibling).getData());
        }
        sibling = sibling.getNextSibling();
    }
}
 
Example 7
Project: tangyuan2   File: XmlNodeWrapper.java   View Source Code Vote up 5 votes
private String getBodyData(Node child) {
	if (child.getNodeType() == Node.CDATA_SECTION_NODE || child.getNodeType() == Node.TEXT_NODE) {
		String data = ((CharacterData) child).getData();
		// TODO data = PropertyParser.parse(data, null);
		return data;
	}
	return null;
}
 
Example 8
Project: Java-APIs   File: AbstractFieldListElement.java   View Source Code Vote up 5 votes
public AbstractFieldListElement(Element element) {
	logger.debug("Constructor - entry");
	fieldList = new Vector<Field>();

	NodeList nodeList = element.getChildNodes();
	for (int n = 0; n < nodeList.getLength(); n++) {
		Node node = nodeList.item(n);
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			Element childElement = (Element) node;
			if ("FIELD".equals(childElement.getNodeName())) {
				addField(new Field(childElement));
			} else {
				logger.trace("Unrecognized child node: '" + childElement.getNodeName() + "' (" + this.getClass().getName() + ")");
			}
		} else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue() != null) && (node.getNodeValue().trim().length() > 0)) {
			logger.trace("Unexpected text node (" + this.getClass().getName() + "): '" + node.getNodeValue() + "'");
		}
	}

	NamedNodeMap namedNodeMap = element.getAttributes();
	if (namedNodeMap != null) {
		for (int a = 0; a < namedNodeMap.getLength(); a++) {
			Attr attributeNode = (Attr) namedNodeMap.item(a);
			if ("TYPE".equals(attributeNode.getName())) {
				setType(attributeNode.getValue());
			} else if ("ABBR".equals(attributeNode.getName())) {
				setAbbreviation(attributeNode.getValue());
			} else {
				logger.trace("Unrecognized attribute: '" + attributeNode.getName() + "' (" + this.getClass().getName() + ")");
			}
		}
	}
	logger.debug("Constructor - exit");
}
 
Example 9
Project: openjdk-jdk10   File: DocumentImpl.java   View Source Code Vote up 5 votes
/**
 * NON-DOM INTERNAL: Pre-mutation context check, in
 * preparation for later generating DOMAttrModified events.
 * Determines whether this node is within an Attr
 * @param node node to get enclosing attribute for
 * @return either a description of that Attr, or null if none such.
 */
protected void saveEnclosingAttr(NodeImpl node) {
    savedEnclosingAttr = null;
    // MUTATION PREPROCESSING AND PRE-EVENTS:
    // If we're within the scope of an Attr and DOMAttrModified
    // was requested, we need to preserve its previous value for
    // that event.
    LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
    if (lc.total > 0) {
        NodeImpl eventAncestor = node;
        while (true) {
            if (eventAncestor == null)
                return;
            int type = eventAncestor.getNodeType();
            if (type == Node.ATTRIBUTE_NODE) {
                EnclosingAttr retval = new EnclosingAttr();
                retval.node = (AttrImpl) eventAncestor;
                retval.oldvalue = retval.node.getNodeValue();
                savedEnclosingAttr = retval;
                return;
            }
            else if (type == Node.ENTITY_REFERENCE_NODE)
                eventAncestor = eventAncestor.parentNode();
            else if (type == Node.TEXT_NODE)
                eventAncestor = eventAncestor.parentNode();
            else
                return;
            // Any other parent means we're not in an Attr
        }
    }
}
 
Example 10
Project: dacapobench   File: RuleSetFactory.java   View Source Code Vote up 5 votes
/**
 * Process a rule descrtiprion node
 * @param rule the rule being constructed
 * @param descriptionNode must be a description element node
 */
private void parseDescriptionNode(Rule rule, Node descriptionNode) {
    NodeList nodeList = descriptionNode.getChildNodes();
    StringBuffer buffer = new StringBuffer();
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node node = nodeList.item(i);
        if (node.getNodeType() == Node.CDATA_SECTION_NODE) {
            buffer.append(node.getNodeValue());
        } else if (node.getNodeType() == Node.TEXT_NODE) {
            buffer.append(node.getNodeValue());
        }
    }
    rule.setDescription(buffer.toString());
}
 
Example 11
Project: OpenJSharp   File: TextImpl.java   View Source Code Vote up 5 votes
/**
 * Concatenates the text of all logically-adjacent text nodes to the
 * right of this node
 * @param node
 * @param buffer
 * @param parent
 * @return true - if execution was stopped because the type of node
 *         other than EntityRef, Text, CDATA is encountered, otherwise
 *         return false
 */
private boolean getWholeTextForward(Node node, StringBuffer buffer, Node parent){
    // boolean to indicate whether node is a child of an entity reference
    boolean inEntRef = false;

    if (parent!=null) {
            inEntRef = parent.getNodeType()==Node.ENTITY_REFERENCE_NODE;
    }

    while (node != null) {
        short type = node.getNodeType();
        if (type == Node.ENTITY_REFERENCE_NODE) {
            if (getWholeTextForward(node.getFirstChild(), buffer, node)){
                return true;
            }
        }
        else if (type == Node.TEXT_NODE ||
                 type == Node.CDATA_SECTION_NODE) {
            ((NodeImpl)node).getTextContent(buffer);
        }
        else {
            return true;
        }

        node = node.getNextSibling();
    }

    // if the parent node is an entity reference node, must
    // check nodes to the right of the parent entity reference node for logically adjacent
    // text nodes
    if (inEntRef) {
        getWholeTextForward(parent.getNextSibling(), buffer, parent.getParentNode());
                    return true;
    }

    return false;
}
 
Example 12
Project: OpenJSharp   File: DOMPrinter.java   View Source Code Vote up 5 votes
public void print(Node node) throws XMLStreamException {
    switch (node.getNodeType()) {
    case Node.DOCUMENT_NODE:
        visitDocument((Document) node);
        break;
    case Node.DOCUMENT_FRAGMENT_NODE:
        visitDocumentFragment((DocumentFragment) node);
        break;
    case Node.ELEMENT_NODE:
        visitElement((Element) node);
        break;
    case Node.TEXT_NODE:
        visitText((Text) node);
        break;
    case Node.CDATA_SECTION_NODE:
        visitCDATASection((CDATASection) node);
        break;
    case Node.PROCESSING_INSTRUCTION_NODE:
        visitProcessingInstruction((ProcessingInstruction) node);
        break;
    case Node.ENTITY_REFERENCE_NODE:
        visitReference((EntityReference) node);
        break;
    case Node.COMMENT_NODE:
        visitComment((Comment) node);
        break;
    case Node.DOCUMENT_TYPE_NODE:
        break;
    case Node.ATTRIBUTE_NODE:
    case Node.ENTITY_NODE:
    default:
        throw new XMLStreamException("Unexpected DOM Node Type "
            + node.getNodeType()
        );
    }
}
 
Example 13
Project: jmt   File: XMLReader.java   View Source Code Vote up 5 votes
/**
 * Helper method that searches for first text node, between all children of current node
 * and returns its value. (This is needed to garbage out all comments)
 * @param elem root node to begin search
 * @return parsed text if found, otherwise null
 */
protected static String findText(Node elem) {
	NodeList tmp = elem.getChildNodes();
	for (int j = 0; j < tmp.getLength(); j++) {
		if (tmp.item(j).getNodeType() == Node.TEXT_NODE) {
			return tmp.item(j).getNodeValue();
		}
	}
	return null;
}
 
Example 14
Project: convertigo-engine   File: TwsDomTreeWrap.java   View Source Code Vote up 4 votes
private static void addNodeInTree2(Node node, Document document, Element parent, int [] index) {
    Element currentElement = createElement2(document, node, index);
    currentElement.setAttribute("type", Short.toString(node.getNodeType()));

    switch (node.getNodeType()) {
        case Node.ELEMENT_NODE:
            currentElement.setAttribute("text", node.getNodeName());
            NamedNodeMap map = node.getAttributes();
            if (node.hasAttributes()) {
                Element attributes = createElement2(document, node, index);
                attributes.setAttribute("text", "Attributes");
                attributes.setAttribute("type", Short.toString(Node.ATTRIBUTE_NODE));
                currentElement.appendChild(attributes);

                for (int i = 0; i < map.getLength(); ++i) {
                    Element attribute = createElement2(document, map.item(i), index);
                    attribute.setAttribute("text", map.item(i).getNodeName() + "=\"" + map.item(i).getNodeValue() + "\"");
                    attribute.setAttribute("type", Short.toString(Node.ATTRIBUTE_NODE));
                    attributes.appendChild(attribute);
                }
            }
            break;

        case Node.TEXT_NODE:
            currentElement.setAttribute("text", node.getNodeValue() == null ? "" : node.getNodeValue().trim());
            break;

        case Node.ENTITY_NODE:
            currentElement.setAttribute("text", "[Entity]");
            break;

        case Node.ENTITY_REFERENCE_NODE:
            currentElement.setAttribute("text", "[Entityref]");
            break;

        case Node.PROCESSING_INSTRUCTION_NODE:
            currentElement.setAttribute("text", "[Pi]");
            break;

        case Node.COMMENT_NODE:
            currentElement.setAttribute("text", "[Comment]");
            break;

        case Node.DOCUMENT_FRAGMENT_NODE:
            currentElement.setAttribute("text", "[Docfgmt]");
            break;

        case Node.DOCUMENT_TYPE_NODE:
            currentElement.setAttribute("text", "[Doctype]");
            break;

        case Node.NOTATION_NODE:
            currentElement.setAttribute("text", "[Notation]");
            break;

        default:
            break;
    }
    parent.appendChild(currentElement);

    NodeList nodeList = node.getChildNodes();
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node currentNode = nodeList.item(i);
        addNodeInTree2(currentNode, document, currentElement, index);
    }
}
 
Example 15
Project: javaide   File: SdkRepoSource.java   View Source Code Vote up 4 votes
/**
 * Helper method used by {@link #findAlternateToolsXml(InputStream)} to duplicate a node
 * and attach it to the given root in the new document.
 */
private Element duplicateNode(Element newRootNode, Element oldNode,
        String namespaceUri, String prefix) {
    // The implementation here is more or less equivalent to
    //
    //    newRoot.appendChild(newDoc.importNode(oldNode, deep=true))
    //
    // except we can't just use importNode() since we need to deal with the fact
    // that the old document is not namespace-aware yet the new one is.

    Document newDoc = newRootNode.getOwnerDocument();
    Element newNode = null;

    String nodeName = oldNode.getNodeName();
    int pos = nodeName.indexOf(':');
    if (pos > 0 && pos < nodeName.length() - 1) {
        nodeName = nodeName.substring(pos + 1);
        newNode = newDoc.createElementNS(namespaceUri, nodeName);
        newNode.setPrefix(prefix);
    } else {
        newNode = newDoc.createElement(nodeName);
    }

    newRootNode.appendChild(newNode);

    // Merge in all the attributes
    NamedNodeMap attrs = oldNode.getAttributes();
    for (int i = 0; i < attrs.getLength(); i++) {
        Attr attr = (Attr) attrs.item(i);
        Attr newAttr = null;

        String attrName = attr.getNodeName();
        pos = attrName.indexOf(':');
        if (pos > 0 && pos < attrName.length() - 1) {
            attrName = attrName.substring(pos + 1);
            newAttr = newDoc.createAttributeNS(namespaceUri, attrName);
            newAttr.setPrefix(prefix);
        } else {
            newAttr = newDoc.createAttribute(attrName);
        }

        newAttr.setNodeValue(attr.getNodeValue());

        if (pos > 0) {
            newNode.getAttributes().setNamedItemNS(newAttr);
        } else {
            newNode.getAttributes().setNamedItem(newAttr);
        }
    }

    // Merge all child elements and texts
    for (Node child = oldNode.getFirstChild(); child != null; child = child.getNextSibling()) {
        if (child.getNodeType() == Node.ELEMENT_NODE) {
            duplicateNode(newNode, (Element) child, namespaceUri, prefix);

        } else if (child.getNodeType() == Node.TEXT_NODE) {
            Text newText = newDoc.createTextNode(child.getNodeValue());
            newNode.appendChild(newText);
        }
    }

    return newNode;
}
 
Example 16
Project: openjdk-jdk10   File: DocumentFragmentImpl.java   View Source Code Vote up 4 votes
/**
 * Override default behavior to call normalize() on this Node's
 * children. It is up to implementors or Node to override normalize()
 * to take action.
 */
public void normalize() {
    // No need to normalize if already normalized.
    if (isNormalized()) {
        return;
    }
    if (needsSyncChildren()) {
        synchronizeChildren();
    }
    ChildNode kid, next;

    for (kid = firstChild; kid != null; kid = next) {
        next = kid.nextSibling;

        // If kid is a text node, we need to check for one of two
        // conditions:
        //   1) There is an adjacent text node
        //   2) There is no adjacent text node, but kid is
        //      an empty text node.
        if ( kid.getNodeType() == Node.TEXT_NODE )
        {
            // If an adjacent text node, merge it with kid
            if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
            {
                ((Text)kid).appendData(next.getNodeValue());
                removeChild( next );
                next = kid; // Don't advance; there might be another.
            }
            else
            {
                // If kid is empty, remove it
                if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
                    removeChild( kid );
                }
            }
        }

        kid.normalize();
    }

    isNormalized(true);
}
 
Example 17
Project: DaUtil   File: XmlUtil.java   View Source Code Vote up 4 votes
public static boolean isBlank(Node node) {
	return node != null && ((node.getNodeType() == Node.TEXT_NODE && StringUtil.isBlank(node.getNodeValue())) || (node.getNodeType() == Node.COMMENT_NODE));
}
 
Example 18
Project: OpenJSharp   File: ElementImpl.java   View Source Code Vote up 4 votes
/**
 * In "normal form" (as read from a source file), there will never be two
 * Text children in succession. But DOM users may create successive Text
 * nodes in the course of manipulating the document. Normalize walks the
 * sub-tree and merges adjacent Texts, as if the DOM had been written out
 * and read back in again. This simplifies implementation of higher-level
 * functions that may want to assume that the document is in standard form.
 * <p>
 * To normalize a Document, normalize its top-level Element child.
 * <p>
 * As of PR-DOM-Level-1-19980818, CDATA -- despite being a subclass of
 * Text -- is considered "markup" and will _not_ be merged either with
 * normal Text or with other CDATASections.
 */
public void normalize() {
    // No need to normalize if already normalized.
    if (isNormalized()) {
        return;
    }
    if (needsSyncChildren()) {
        synchronizeChildren();
    }
    ChildNode kid, next;
    for (kid = firstChild; kid != null; kid = next) {
        next = kid.nextSibling;

        // If kid is a text node, we need to check for one of two
        // conditions:
        //   1) There is an adjacent text node
        //   2) There is no adjacent text node, but kid is
        //      an empty text node.
        if ( kid.getNodeType() == Node.TEXT_NODE )
        {
            // If an adjacent text node, merge it with kid
            if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
            {
                ((Text)kid).appendData(next.getNodeValue());
                removeChild( next );
                next = kid; // Don't advance; there might be another.
            }
            else
            {
                // If kid is empty, remove it
                if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
                    removeChild( kid );
                }
            }
        }

        // Otherwise it might be an Element, which is handled recursively
        else if (kid.getNodeType() == Node.ELEMENT_NODE) {
            kid.normalize();
        }
    }

    // We must also normalize all of the attributes
    if ( attributes!=null )
    {
        for( int i=0; i<attributes.getLength(); ++i )
        {
            Node attr = attributes.item(i);
            attr.normalize();
        }
    }

    // changed() will have occurred when the removeChild() was done,
    // so does not have to be reissued.

    isNormalized(true);
}
 
Example 19
Project: OpenJSharp   File: FuncHere.java   View Source Code Vote up 4 votes
/**
 * The here function returns a node-set containing the attribute or
 * processing instruction node or the parent element of the text node
 * that directly bears the XPath expression.  This expression results
 * in an error if the containing XPath expression does not appear in the
 * same XML document against which the XPath expression is being evaluated.
 *
 * @param xctxt
 * @return the xobject
 * @throws javax.xml.transform.TransformerException
 */
@Override
public XObject execute(XPathContext xctxt)
    throws javax.xml.transform.TransformerException {

    Node xpathOwnerNode = (Node) xctxt.getOwnerObject();

    if (xpathOwnerNode == null) {
        return null;
    }

    int xpathOwnerNodeDTM = xctxt.getDTMHandleFromNode(xpathOwnerNode);

    int currentNode = xctxt.getCurrentNode();
    DTM dtm = xctxt.getDTM(currentNode);
    int docContext = dtm.getDocument();

    if (DTM.NULL == docContext) {
        error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null);
    }

    {
        // check whether currentNode and the node containing the XPath expression
        // are in the same document
        Document currentDoc =
            XMLUtils.getOwnerDocument(dtm.getNode(currentNode));
        Document xpathOwnerDoc = XMLUtils.getOwnerDocument(xpathOwnerNode);

        if (currentDoc != xpathOwnerDoc) {
            throw new TransformerException(I18n.translate("xpath.funcHere.documentsDiffer"));
        }
    }

    XNodeSet nodes = new XNodeSet(xctxt.getDTMManager());
    NodeSetDTM nodeSet = nodes.mutableNodeset();

    {
        int hereNode = DTM.NULL;

        switch (dtm.getNodeType(xpathOwnerNodeDTM)) {

        case Node.ATTRIBUTE_NODE :
        case Node.PROCESSING_INSTRUCTION_NODE : {
            // returns a node-set containing the attribute /  processing instruction node
            hereNode = xpathOwnerNodeDTM;

            nodeSet.addNode(hereNode);

            break;
        }
        case Node.TEXT_NODE : {
            // returns a node-set containing the parent element of the
            // text node that directly bears the XPath expression
            hereNode = dtm.getParent(xpathOwnerNodeDTM);

            nodeSet.addNode(hereNode);

            break;
        }
        default :
            break;
        }
    }

    /** $todo$ Do I have to do this detach() call? */
    nodeSet.detach();

    return nodes;
}
 
Example 20
Project: OpenDiabetes   File: JDBCSQLXML.java   View Source Code Vote up 4 votes
/**
 * Receive notification of character data.
 *
 * <p>The Parser will call this method to report each chunk of
 * character data.  SAX parsers may return all contiguous character
 * data in a single chunk, or they may split it into several
 * chunks; however, all of the characters in any single event
 * must come from the same external entity so that the Locator
 * provides useful information.</p>
 *
 * <p>The application must not attempt to read from the array
 * outside of the specified range.</p>
 *
 * <p>Individual characters may consist of more than one Java
 * <code>char</code> value.  There are two important cases where this
 * happens, because characters can't be represented in just sixteen bits.
 * In one case, characters are represented in a <em>Surrogate Pair</em>,
 * using two special Unicode values. Such characters are in the so-called
 * "Astral Planes", with a code point above U+FFFF.  A second case involves
 * composite characters, such as a base character combining with one or
 * more accent characters. </p>
 *
 * <p> Your code should not assume that algorithms using
 * <code>char</code>-at-a-time idioms will be working in character
 * units; in some cases they will split characters.  This is relevant
 * wherever XML permits arbitrary characters, such as attribute values,
 * processing instruction data, and comments as well as in data reported
 * from this method.  It's also generally relevant whenever Java code
 * manipulates internationalized text; the issue isn't unique to XML.</p>
 *
 * <p>Note that some parsers will report whitespace in element
 * content using the {@link #ignorableWhitespace ignorableWhitespace}
 * method rather than this one (validating parsers <em>must</em>
 * do so).</p>
 *
 * @param ch the characters from the XML document
 * @param start the start position in the array
 * @param length the number of characters to read from the array
 * @throws org.xml.sax.SAXException any SAX exception, possibly
 *            wrapping another exception
 * @see #ignorableWhitespace
 * @see org.xml.sax.Locator
 */
public void characters(char[] ch, int start,
                       int length) throws SAXException {

    checkClosed();

    Node   node = getCurrentNode().getLastChild();
    String s    = new String(ch, start, length);

    if ((node != null) && (node.getNodeType() == Node.TEXT_NODE)) {
        ((Text) node).appendData(s);
    } else {
        Text text = getDocument().createTextNode(s);

        getCurrentNode().appendChild(text);
    }
}