/*
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
 */
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sun.org.apache.xml.internal.serializer.dom3;

import com.sun.org.apache.xerces.internal.util.XML11Char;
import com.sun.org.apache.xerces.internal.util.XMLChar;
import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
import com.sun.org.apache.xml.internal.serializer.utils.Utils;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMError;
import org.w3c.dom.DOMErrorHandler;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.ls.LSSerializerFilter;
import org.w3c.dom.traversal.NodeFilter;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.LocatorImpl;

Built on org.apache.xml.serializer.TreeWalker and adds functionality to traverse and serialize a DOM Node (Level 2 or Level 3) as specified in the DOM Level 3 LS Recommedation by evaluating and applying DOMConfiguration parameters and filters if any during serialization.
@xsl.usageinternal
/** * Built on org.apache.xml.serializer.TreeWalker and adds functionality to * traverse and serialize a DOM Node (Level 2 or Level 3) as specified in * the DOM Level 3 LS Recommedation by evaluating and applying DOMConfiguration * parameters and filters if any during serialization. * * @xsl.usage internal */
final class DOM3TreeWalker {
The SerializationHandler, it extends ContentHandler and when this class is instantiated via the constructor provided, a SerializationHandler object is passed to it.
/** * The SerializationHandler, it extends ContentHandler and when * this class is instantiated via the constructor provided, a * SerializationHandler object is passed to it. */
private SerializationHandler fSerializer = null; /** We do not need DOM2Helper since DOM Level 3 LS applies to DOM Level 2 or newer */
Locator object for this TreeWalker
/** Locator object for this TreeWalker */
private LocatorImpl fLocator = new LocatorImpl();
ErrorHandler
/** ErrorHandler */
private DOMErrorHandler fErrorHandler = null;
LSSerializerFilter
/** LSSerializerFilter */
private LSSerializerFilter fFilter = null;
If the serializer is an instance of a LexicalHandler
/** If the serializer is an instance of a LexicalHandler */
private LexicalHandler fLexicalHandler = null; private int fWhatToShowFilter;
New Line character to use in serialization
/** New Line character to use in serialization */
private String fNewLine = null;
DOMConfiguration Properties
/** DOMConfiguration Properties */
private Properties fDOMConfigProperties = null;
Keeps track if we are in an entity reference when entities=true
/** Keeps track if we are in an entity reference when entities=true */
private boolean fInEntityRef = false;
Stores the version of the XML document to be serialize
/** Stores the version of the XML document to be serialize */
private String fXMLVersion = null;
XML Version, default 1.0
/** XML Version, default 1.0 */
private boolean fIsXMLVersion11 = false;
Is the Node a Level 3 DOM node
/** Is the Node a Level 3 DOM node */
private boolean fIsLevel3DOM = false;
DOM Configuration Parameters
/** DOM Configuration Parameters */
private int fFeatures = 0;
Flag indicating whether following text to be processed is raw text
/** Flag indicating whether following text to be processed is raw text */
boolean fNextIsRaw = false; // private static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; // private static final String XMLNS_PREFIX = "xmlns"; // private static final String XML_URI = "http://www.w3.org/XML/1998/namespace"; // private static final String XML_PREFIX = "xml";
stores namespaces in scope
/** stores namespaces in scope */
protected NamespaceSupport fNSBinder;
stores all namespace bindings on the current element
/** stores all namespace bindings on the current element */
protected NamespaceSupport fLocalNSBinder;
stores the current element depth
/** stores the current element depth */
private int fElementDepth = 0; // *********************************************************************** // DOMConfiguration paramter settings // *********************************************************************** // Parameter canonical-form, true [optional] - NOT SUPPORTED private final static int CANONICAL = 0x1 << 0; // Parameter cdata-sections, true [required] (default) private final static int CDATA = 0x1 << 1; // Parameter check-character-normalization, true [optional] - NOT SUPPORTED private final static int CHARNORMALIZE = 0x1 << 2; // Parameter comments, true [required] (default) private final static int COMMENTS = 0x1 << 3; // Parameter datatype-normalization, true [optional] - NOT SUPPORTED private final static int DTNORMALIZE = 0x1 << 4; // Parameter element-content-whitespace, true [required] (default) - value - false [optional] NOT SUPPORTED private final static int ELEM_CONTENT_WHITESPACE = 0x1 << 5; // Parameter entities, true [required] (default) private final static int ENTITIES = 0x1 << 6; // Parameter infoset, true [required] (default), false has no effect --> True has no effect for the serializer private final static int INFOSET = 0x1 << 7; // Parameter namespaces, true [required] (default) private final static int NAMESPACES = 0x1 << 8; // Parameter namespace-declarations, true [required] (default) private final static int NAMESPACEDECLS = 0x1 << 9; // Parameter normalize-characters, true [optional] - NOT SUPPORTED private final static int NORMALIZECHARS = 0x1 << 10; // Parameter split-cdata-sections, true [required] (default) private final static int SPLITCDATA = 0x1 << 11; // Parameter validate, true [optional] - NOT SUPPORTED private final static int VALIDATE = 0x1 << 12; // Parameter validate-if-schema, true [optional] - NOT SUPPORTED private final static int SCHEMAVALIDATE = 0x1 << 13; // Parameter split-cdata-sections, true [required] (default) private final static int WELLFORMED = 0x1 << 14; // Parameter discard-default-content, true [required] (default) // Not sure how this will be used in level 2 Documents private final static int DISCARDDEFAULT = 0x1 << 15; // Parameter format-pretty-print, true [optional] private final static int PRETTY_PRINT = 0x1 << 16; // Parameter ignore-unknown-character-denormalizations, true [required] (default) // We currently do not support XML 1.1 character normalization private final static int IGNORE_CHAR_DENORMALIZE = 0x1 << 17; // Parameter discard-default-content, true [required] (default) private final static int XMLDECL = 0x1 << 18;
Constructor.
Params:
  • contentHandler – serialHandler The implemention of the SerializationHandler interface
/** * Constructor. * @param contentHandler serialHandler The implemention of the SerializationHandler interface */
DOM3TreeWalker( SerializationHandler serialHandler, DOMErrorHandler errHandler, LSSerializerFilter filter, String newLine) { fSerializer = serialHandler; //fErrorHandler = errHandler == null ? new DOMErrorHandlerImpl() : errHandler; // Should we be using the default? fErrorHandler = errHandler; fFilter = filter; fLexicalHandler = null; fNewLine = newLine; fNSBinder = new NamespaceSupport(); fLocalNSBinder = new NamespaceSupport(); fDOMConfigProperties = fSerializer.getOutputFormat(); fSerializer.setDocumentLocator(fLocator); initProperties(fDOMConfigProperties); }
Perform a pre-order traversal non-recursive style. Note that TreeWalker assumes that the subtree is intended to represent a complete (though not necessarily well-formed) document and, during a traversal, startDocument and endDocument will always be issued to the SAX listener.
Params:
  • pos – Node in the tree where to start traversal
Throws:
  • TransformerException –
/** * Perform a pre-order traversal non-recursive style. * * Note that TreeWalker assumes that the subtree is intended to represent * a complete (though not necessarily well-formed) document and, during a * traversal, startDocument and endDocument will always be issued to the * SAX listener. * * @param pos Node in the tree where to start traversal * * @throws TransformerException */
public void traverse(Node pos) throws org.xml.sax.SAXException { this.fSerializer.startDocument(); // Determine if the Node is a DOM Level 3 Core Node. if (pos.getNodeType() != Node.DOCUMENT_NODE) { Document ownerDoc = pos.getOwnerDocument(); if (ownerDoc != null && ownerDoc.getImplementation().hasFeature("Core", "3.0")) { fIsLevel3DOM = true; } } else { if (((Document) pos) .getImplementation() .hasFeature("Core", "3.0")) { fIsLevel3DOM = true; } } if (fSerializer instanceof LexicalHandler) { fLexicalHandler = ((LexicalHandler) this.fSerializer); } if (fFilter != null) fWhatToShowFilter = fFilter.getWhatToShow(); Node top = pos; while (null != pos) { startNode(pos); Node nextNode = null; nextNode = pos.getFirstChild(); while (null == nextNode) { endNode(pos); if (top.equals(pos)) break; nextNode = pos.getNextSibling(); if (null == nextNode) { pos = pos.getParentNode(); if ((null == pos) || (top.equals(pos))) { if (null != pos) endNode(pos); nextNode = null; break; } } } pos = nextNode; } this.fSerializer.endDocument(); }
Perform a pre-order traversal non-recursive style. Note that TreeWalker assumes that the subtree is intended to represent a complete (though not necessarily well-formed) document and, during a traversal, startDocument and endDocument will always be issued to the SAX listener.
Params:
  • pos – Node in the tree where to start traversal
  • top – Node in the tree where to end traversal
Throws:
  • TransformerException –
/** * Perform a pre-order traversal non-recursive style. * Note that TreeWalker assumes that the subtree is intended to represent * a complete (though not necessarily well-formed) document and, during a * traversal, startDocument and endDocument will always be issued to the * SAX listener. * * @param pos Node in the tree where to start traversal * @param top Node in the tree where to end traversal * * @throws TransformerException */
public void traverse(Node pos, Node top) throws org.xml.sax.SAXException { this.fSerializer.startDocument(); // Determine if the Node is a DOM Level 3 Core Node. if (pos.getNodeType() != Node.DOCUMENT_NODE) { Document ownerDoc = pos.getOwnerDocument(); if (ownerDoc != null && ownerDoc.getImplementation().hasFeature("Core", "3.0")) { fIsLevel3DOM = true; } } else { if (((Document) pos) .getImplementation() .hasFeature("Core", "3.0")) { fIsLevel3DOM = true; } } if (fSerializer instanceof LexicalHandler) { fLexicalHandler = ((LexicalHandler) this.fSerializer); } if (fFilter != null) fWhatToShowFilter = fFilter.getWhatToShow(); while (null != pos) { startNode(pos); Node nextNode = null; nextNode = pos.getFirstChild(); while (null == nextNode) { endNode(pos); if ((null != top) && top.equals(pos)) break; nextNode = pos.getNextSibling(); if (null == nextNode) { pos = pos.getParentNode(); if ((null == pos) || ((null != top) && top.equals(pos))) { nextNode = null; break; } } } pos = nextNode; } this.fSerializer.endDocument(); }
Optimized dispatch of characters.
/** * Optimized dispatch of characters. */
private final void dispatachChars(Node node) throws org.xml.sax.SAXException { if (fSerializer != null) { String data = ((Text) node).getData(); this.fSerializer.characters(data.toCharArray(), 0, data.length()); } }
Start processing given node
Params:
  • node – Node to process
Throws:
/** * Start processing given node * * @param node Node to process * * @throws org.xml.sax.SAXException */
protected void startNode(Node node) throws org.xml.sax.SAXException { if (node instanceof Locator) { Locator loc = (Locator) node; fLocator.setColumnNumber(loc.getColumnNumber()); fLocator.setLineNumber(loc.getLineNumber()); fLocator.setPublicId(loc.getPublicId()); fLocator.setSystemId(loc.getSystemId()); } else { fLocator.setColumnNumber(0); fLocator.setLineNumber(0); } switch (node.getNodeType()) { case Node.DOCUMENT_TYPE_NODE : serializeDocType((DocumentType) node, true); break; case Node.COMMENT_NODE : serializeComment((Comment) node); break; case Node.DOCUMENT_FRAGMENT_NODE : // Children are traversed break; case Node.DOCUMENT_NODE : break; case Node.ELEMENT_NODE : serializeElement((Element) node, true); break; case Node.PROCESSING_INSTRUCTION_NODE : serializePI((ProcessingInstruction) node); break; case Node.CDATA_SECTION_NODE : serializeCDATASection((CDATASection) node); break; case Node.TEXT_NODE : serializeText((Text) node); break; case Node.ENTITY_REFERENCE_NODE : serializeEntityReference((EntityReference) node, true); break; default : } }
End processing of given node
Params:
  • node – Node we just finished processing
Throws:
/** * End processing of given node * * * @param node Node we just finished processing * * @throws org.xml.sax.SAXException */
protected void endNode(Node node) throws org.xml.sax.SAXException { switch (node.getNodeType()) { case Node.DOCUMENT_NODE : break; case Node.DOCUMENT_TYPE_NODE : serializeDocType((DocumentType) node, false); break; case Node.ELEMENT_NODE : serializeElement((Element) node, false); break; case Node.CDATA_SECTION_NODE : break; case Node.ENTITY_REFERENCE_NODE : serializeEntityReference((EntityReference) node, false); break; default : } } // *********************************************************************** // Node serialization methods // ***********************************************************************
Applies a filter on the node to serialize
Params:
  • node – The Node to serialize
Returns:True if the node is to be serialized else false if the node is to be rejected or skipped.
/** * Applies a filter on the node to serialize * * @param node The Node to serialize * @return True if the node is to be serialized else false if the node * is to be rejected or skipped. */
protected boolean applyFilter(Node node, int nodeType) { if (fFilter != null && (fWhatToShowFilter & nodeType) != 0) { short code = fFilter.acceptNode(node); switch (code) { case NodeFilter.FILTER_REJECT : case NodeFilter.FILTER_SKIP : return false; // skip the node default : // fall through.. } } return true; }
Serializes a Document Type Node.
Params:
  • node – The Docuemnt Type Node to serialize
  • bStart – Invoked at the start or end of node. Default true.
/** * Serializes a Document Type Node. * * @param node The Docuemnt Type Node to serialize * @param bStart Invoked at the start or end of node. Default true. */
protected void serializeDocType(DocumentType node, boolean bStart) throws SAXException { // The DocType and internalSubset can not be modified in DOM and is // considered to be well-formed as the outcome of successful parsing. String docTypeName = node.getNodeName(); String publicId = node.getPublicId(); String systemId = node.getSystemId(); String internalSubset = node.getInternalSubset(); //DocumentType nodes are never passed to the filter if (internalSubset != null && !"".equals(internalSubset)) { if (bStart) { try { // The Serializer does not provide a way to write out the // DOCTYPE internal subset via an event call, so we write it // out here. Writer writer = fSerializer.getWriter(); StringBuffer dtd = new StringBuffer(); dtd.append("<!DOCTYPE "); dtd.append(docTypeName); if (null != publicId) { dtd.append(" PUBLIC \""); dtd.append(publicId); dtd.append('\"'); } if (null != systemId) { if (null == publicId) { dtd.append(" SYSTEM \""); } else { dtd.append(" \""); } dtd.append(systemId); dtd.append('\"'); } dtd.append(" [ "); dtd.append(fNewLine); dtd.append(internalSubset); dtd.append("]>"); dtd.append(fNewLine); writer.write(dtd.toString()); writer.flush(); } catch (IOException e) { throw new SAXException(Utils.messages.createMessage( MsgKey.ER_WRITING_INTERNAL_SUBSET, null), e); } } // else if !bStart do nothing } else { if (bStart) { if (fLexicalHandler != null) { fLexicalHandler.startDTD(docTypeName, publicId, systemId); } } else { if (fLexicalHandler != null) { fLexicalHandler.endDTD(); } } } }
Serializes a Comment Node.
Params:
  • node – The Comment Node to serialize
/** * Serializes a Comment Node. * * @param node The Comment Node to serialize */
protected void serializeComment(Comment node) throws SAXException { // comments=true if ((fFeatures & COMMENTS) != 0) { String data = node.getData(); // well-formed=true if ((fFeatures & WELLFORMED) != 0) { isCommentWellFormed(data); } if (fLexicalHandler != null) { // apply the LSSerializer filter after the operations requested by the // DOMConfiguration parameters have been applied if (!applyFilter(node, NodeFilter.SHOW_COMMENT)) { return; } fLexicalHandler.comment(data.toCharArray(), 0, data.length()); } } }
Serializes an Element Node.
Params:
  • node – The Element Node to serialize
  • bStart – Invoked at the start or end of node.
/** * Serializes an Element Node. * * @param node The Element Node to serialize * @param bStart Invoked at the start or end of node. */
protected void serializeElement(Element node, boolean bStart) throws SAXException { if (bStart) { fElementDepth++; // We use the Xalan specific startElement and starPrefixMapping calls // (and addAttribute and namespaceAfterStartElement) as opposed to // SAX specific, for performance reasons as they reduce the overhead // of creating an AttList object upfront. // well-formed=true if ((fFeatures & WELLFORMED) != 0) { isElementWellFormed(node); } // REVISIT: We apply the LSSerializer filter for elements before // namesapce fixup if (!applyFilter(node, NodeFilter.SHOW_ELEMENT)) { return; } // namespaces=true, record and fixup namspaced element if ((fFeatures & NAMESPACES) != 0) { fNSBinder.pushContext(); fLocalNSBinder.reset(); recordLocalNSDecl(node); fixupElementNS(node); } // Namespace normalization fSerializer.startElement( node.getNamespaceURI(), node.getLocalName(), node.getNodeName()); serializeAttList(node); } else { fElementDepth--; // apply the LSSerializer filter if (!applyFilter(node, NodeFilter.SHOW_ELEMENT)) { return; } this.fSerializer.endElement( node.getNamespaceURI(), node.getLocalName(), node.getNodeName()); // since endPrefixMapping was not used by SerializationHandler it was removed // for performance reasons. if ((fFeatures & NAMESPACES) != 0 ) { fNSBinder.popContext(); } } }
Serializes the Attr Nodes of an Element.
Params:
  • node – The OwnerElement whose Attr Nodes are to be serialized.
/** * Serializes the Attr Nodes of an Element. * * @param node The OwnerElement whose Attr Nodes are to be serialized. */
protected void serializeAttList(Element node) throws SAXException { NamedNodeMap atts = node.getAttributes(); int nAttrs = atts.getLength(); for (int i = 0; i < nAttrs; i++) { Node attr = atts.item(i); String localName = attr.getLocalName(); String attrName = attr.getNodeName(); String attrPrefix = attr.getPrefix() == null ? "" : attr.getPrefix(); String attrValue = attr.getNodeValue(); // Determine the Attr's type. String type = null; if (fIsLevel3DOM) { type = ((Attr) attr).getSchemaTypeInfo().getTypeName(); } type = type == null ? "CDATA" : type; String attrNS = attr.getNamespaceURI(); if (attrNS !=null && attrNS.length() == 0) { attrNS=null; // we must remove prefix for this attribute attrName=attr.getLocalName(); } boolean isSpecified = ((Attr) attr).getSpecified(); boolean addAttr = true; boolean applyFilter = false; boolean xmlnsAttr = attrName.equals("xmlns") || attrName.startsWith("xmlns:"); // well-formed=true if ((fFeatures & WELLFORMED) != 0) { isAttributeWellFormed(attr); } //----------------------------------------------------------------- // start Attribute namespace fixup //----------------------------------------------------------------- // namespaces=true, normalize all non-namespace attributes // Step 3. Attribute if ((fFeatures & NAMESPACES) != 0 && !xmlnsAttr) { // If the Attr has a namespace URI if (attrNS != null) { attrPrefix = attrPrefix == null ? "" : attrPrefix; String declAttrPrefix = fNSBinder.getPrefix(attrNS); String declAttrNS = fNSBinder.getURI(attrPrefix); // attribute has no prefix (default namespace decl does not apply to // attributes) // OR // attribute prefix is not declared // OR // conflict: attribute has a prefix that conflicts with a binding if ("".equals(attrPrefix) || "".equals(declAttrPrefix) || !attrPrefix.equals(declAttrPrefix)) { // namespaceURI matches an in scope declaration of one or // more prefixes if (declAttrPrefix != null && !"".equals(declAttrPrefix)) { // pick the prefix that was found and change attribute's // prefix and nodeName. attrPrefix = declAttrPrefix; if (declAttrPrefix.length() > 0 ) { attrName = declAttrPrefix + ":" + localName; } else { attrName = localName; } } else { // The current prefix is not null and it has no in scope // declaration if (attrPrefix != null && !"".equals(attrPrefix) && declAttrNS == null) { // declare this prefix if ((fFeatures & NAMESPACEDECLS) != 0) { fSerializer.addAttribute(XMLNS_URI, attrPrefix, XMLNS_PREFIX + ":" + attrPrefix, "CDATA", attrNS); fNSBinder.declarePrefix(attrPrefix, attrNS); fLocalNSBinder.declarePrefix(attrPrefix, attrNS); } } else { // find a prefix following the pattern "NS" +index // (starting at 1) // make sure this prefix is not declared in the current // scope. int counter = 1; attrPrefix = "NS" + counter++; while (fLocalNSBinder.getURI(attrPrefix) != null) { attrPrefix = "NS" + counter++; } // change attribute's prefix and Name attrName = attrPrefix + ":" + localName; // create a local namespace declaration attribute // Add the xmlns declaration attribute if ((fFeatures & NAMESPACEDECLS) != 0) { fSerializer.addAttribute(XMLNS_URI, attrPrefix, XMLNS_PREFIX + ":" + attrPrefix, "CDATA", attrNS); fNSBinder.declarePrefix(attrPrefix, attrNS); fLocalNSBinder.declarePrefix(attrPrefix, attrNS); } } } } } else { // if the Attr has no namespace URI // Attr has no localName if (localName == null) { // DOM Level 1 node! String msg = Utils.messages.createMessage( MsgKey.ER_NULL_LOCAL_ELEMENT_NAME, new Object[] { attrName }); if (fErrorHandler != null) { fErrorHandler .handleError(new DOMErrorImpl( DOMError.SEVERITY_ERROR, msg, MsgKey.ER_NULL_LOCAL_ELEMENT_NAME, null, null, null)); } } else { // uri=null and no colon // attr has no namespace URI and no prefix // no action is required, since attrs don't use default } } } // discard-default-content=true // Default attr's are not passed to the filter and this contraint // is applied only when discard-default-content=true // What about default xmlns attributes???? check for xmlnsAttr if ((((fFeatures & DISCARDDEFAULT) != 0) && isSpecified) || ((fFeatures & DISCARDDEFAULT) == 0)) { applyFilter = true; } else { addAttr = false; } if (applyFilter) { // apply the filter for Attributes that are not default attributes // or namespace decl attributes if (fFilter != null && (fFilter.getWhatToShow() & NodeFilter.SHOW_ATTRIBUTE) != 0) { if (!xmlnsAttr) { short code = fFilter.acceptNode(attr); switch (code) { case NodeFilter.FILTER_REJECT : case NodeFilter.FILTER_SKIP : addAttr = false; break; default : //fall through.. } } } } // if the node is a namespace node if (addAttr && xmlnsAttr) { // If namespace-declarations=true, add the node , else don't add it if ((fFeatures & NAMESPACEDECLS) != 0) { // The namespace may have been fixed up, in that case don't add it. if (localName != null && !"".equals(localName)) { fSerializer.addAttribute(attrNS, localName, attrName, type, attrValue); } } } else if ( addAttr && !xmlnsAttr) { // if the node is not a namespace node // If namespace-declarations=true, add the node with the Attr nodes namespaceURI // else add the node setting it's namespace to null or else the serializer will later // attempt to add a xmlns attr for the prefixed attribute if (((fFeatures & NAMESPACEDECLS) != 0) && (attrNS != null)) { fSerializer.addAttribute( attrNS, localName, attrName, type, attrValue); } else { fSerializer.addAttribute( "", localName, attrName, type, attrValue); } } // if (xmlnsAttr && ((fFeatures & NAMESPACEDECLS) != 0)) { int index; // Use "" instead of null, as Xerces likes "" for the // name of the default namespace. Fix attributed // to "Steven Murray" <smurray@ebt.com>. String prefix = (index = attrName.indexOf(":")) < 0 ? "" : attrName.substring(index + 1); if (!"".equals(prefix)) { fSerializer.namespaceAfterStartElement(prefix, attrValue); } } } }
Serializes an ProcessingInstruction Node.
Params:
  • node – The ProcessingInstruction Node to serialize
/** * Serializes an ProcessingInstruction Node. * * @param node The ProcessingInstruction Node to serialize */
protected void serializePI(ProcessingInstruction node) throws SAXException { ProcessingInstruction pi = node; String name = pi.getNodeName(); // well-formed=true if ((fFeatures & WELLFORMED) != 0) { isPIWellFormed(node); } // apply the LSSerializer filter if (!applyFilter(node, NodeFilter.SHOW_PROCESSING_INSTRUCTION)) { return; } // String data = pi.getData(); if (name.equals("xslt-next-is-raw")) { fNextIsRaw = true; } else { this.fSerializer.processingInstruction(name, pi.getData()); } }
Serializes an CDATASection Node.
Params:
  • node – The CDATASection Node to serialize
/** * Serializes an CDATASection Node. * * @param node The CDATASection Node to serialize */
protected void serializeCDATASection(CDATASection node) throws SAXException { // well-formed=true if ((fFeatures & WELLFORMED) != 0) { isCDATASectionWellFormed(node); } // cdata-sections = true if ((fFeatures & CDATA) != 0) { // split-cdata-sections = true // Assumption: This parameter has an effect only when // cdata-sections=true // ToStream, by default splits cdata-sections. Hence the check // below. String nodeValue = node.getNodeValue(); int endIndex = nodeValue.indexOf("]]>"); if ((fFeatures & SPLITCDATA) != 0) { if (endIndex >= 0) { // The first node split will contain the ]] markers String relatedData = nodeValue.substring(0, endIndex + 2); String msg = Utils.messages.createMessage( MsgKey.ER_CDATA_SECTIONS_SPLIT, null); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_WARNING, msg, MsgKey.ER_CDATA_SECTIONS_SPLIT, null, relatedData, null)); } } } else { if (endIndex >= 0) { // The first node split will contain the ]] markers String relatedData = nodeValue.substring(0, endIndex + 2); String msg = Utils.messages.createMessage( MsgKey.ER_CDATA_SECTIONS_SPLIT, null); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_ERROR, msg, MsgKey.ER_CDATA_SECTIONS_SPLIT)); } // Report an error and return. What error??? return; } } // apply the LSSerializer filter if (!applyFilter(node, NodeFilter.SHOW_CDATA_SECTION)) { return; } // splits the cdata-section if (fLexicalHandler != null) { fLexicalHandler.startCDATA(); } dispatachChars(node); if (fLexicalHandler != null) { fLexicalHandler.endCDATA(); } } else { dispatachChars(node); } }
Serializes an Text Node.
Params:
  • node – The Text Node to serialize
/** * Serializes an Text Node. * * @param node The Text Node to serialize */
protected void serializeText(Text node) throws SAXException { if (fNextIsRaw) { fNextIsRaw = false; fSerializer.processingInstruction( javax.xml.transform.Result.PI_DISABLE_OUTPUT_ESCAPING, ""); dispatachChars(node); fSerializer.processingInstruction( javax.xml.transform.Result.PI_ENABLE_OUTPUT_ESCAPING, ""); } else { // keep track of dispatch or not to avoid duplicaiton of filter code boolean bDispatch = false; // well-formed=true if ((fFeatures & WELLFORMED) != 0) { isTextWellFormed(node); } // if the node is whitespace // Determine the Attr's type. boolean isElementContentWhitespace = false; if (fIsLevel3DOM) { isElementContentWhitespace = node.isElementContentWhitespace(); } if (isElementContentWhitespace) { // element-content-whitespace=true if ((fFeatures & ELEM_CONTENT_WHITESPACE) != 0) { bDispatch = true; } } else { bDispatch = true; } // apply the LSSerializer filter if (!applyFilter(node, NodeFilter.SHOW_TEXT)) { return; } if (bDispatch && (!fSerializer.getIndent() || !node.getData().replace('\n', ' ').trim().isEmpty())) { dispatachChars(node); } } }
Serializes an EntityReference Node.
Params:
  • node – The EntityReference Node to serialize
  • bStart – Inicates if called from start or endNode
/** * Serializes an EntityReference Node. * * @param node The EntityReference Node to serialize * @param bStart Inicates if called from start or endNode */
protected void serializeEntityReference( EntityReference node, boolean bStart) throws SAXException { if (bStart) { EntityReference eref = node; // entities=true if ((fFeatures & ENTITIES) != 0) { // perform well-formedness and other checking only if // entities = true // well-formed=true if ((fFeatures & WELLFORMED) != 0) { isEntityReferneceWellFormed(node); } // check "unbound-prefix-in-entity-reference" [fatal] // Raised if the configuration parameter "namespaces" is set to true if ((fFeatures & NAMESPACES) != 0) { checkUnboundPrefixInEntRef(node); } // The filter should not apply in this case, since the // EntityReference is not being expanded. // should we pass entity reference nodes to the filter??? } // if "entities" is true, or EntityReference node has no children, // it will be serialized as the form "&entityName;" in the output. if (fLexicalHandler != null && ((fFeatures & ENTITIES) != 0 || !node.hasChildNodes())) { // startEntity outputs only Text but not Element, Attr, Comment // and PI child nodes. It does so by setting the m_inEntityRef // in ToStream and using this to decide if a node is to be // serialized or not. fLexicalHandler.startEntity(eref.getNodeName()); } } else { EntityReference eref = node; // entities=true or false, if (fLexicalHandler != null) { fLexicalHandler.endEntity(eref.getNodeName()); } } } // *********************************************************************** // Methods to check well-formedness // ***********************************************************************
Taken from org.apache.xerces.dom.CoreDocumentImpl Check the string against XML's definition of acceptable names for elements and attributes and so on using the XMLCharacterProperties utility class
/** * Taken from org.apache.xerces.dom.CoreDocumentImpl * * Check the string against XML's definition of acceptable names for * elements and attributes and so on using the XMLCharacterProperties * utility class */
protected boolean isXMLName(String s, boolean xml11Version) { if (s == null) { return false; } if (!xml11Version) return XMLChar.isValidName(s); else return XML11Char.isXML11ValidName(s); }
Taken from org.apache.xerces.dom.CoreDocumentImpl Checks if the given qualified name is legal with respect to the version of XML to which this document must conform.
Params:
  • prefix – prefix of qualified name
  • local – local part of qualified name
/** * Taken from org.apache.xerces.dom.CoreDocumentImpl * * Checks if the given qualified name is legal with respect * to the version of XML to which this document must conform. * * @param prefix prefix of qualified name * @param local local part of qualified name */
protected boolean isValidQName( String prefix, String local, boolean xml11Version) { // check that both prefix and local part match NCName if (local == null) return false; boolean validNCName = false; if (!xml11Version) { validNCName = (prefix == null || XMLChar.isValidNCName(prefix)) && XMLChar.isValidNCName(local); } else { validNCName = (prefix == null || XML11Char.isXML11ValidNCName(prefix)) && XML11Char.isXML11ValidNCName(local); } return validNCName; }
Checks if a XML character is well-formed
Params:
  • characters – A String of characters to be checked for Well-Formedness
  • refInvalidChar – A reference to the character to be returned that was determined invalid.
/** * Checks if a XML character is well-formed * * @param characters A String of characters to be checked for Well-Formedness * @param refInvalidChar A reference to the character to be returned that was determined invalid. */
protected boolean isWFXMLChar(String chardata, Character refInvalidChar) { if (chardata == null || (chardata.length() == 0)) { return true; } char[] dataarray = chardata.toCharArray(); int datalength = dataarray.length; // version of the document is XML 1.1 if (fIsXMLVersion11) { //we need to check all characters as per production rules of XML11 int i = 0; while (i < datalength) { if (XML11Char.isXML11Invalid(dataarray[i++])) { // check if this is a supplemental character char ch = dataarray[i - 1]; if (XMLChar.isHighSurrogate(ch) && i < datalength) { char ch2 = dataarray[i++]; if (XMLChar.isLowSurrogate(ch2) && XMLChar.isSupplemental( XMLChar.supplemental(ch, ch2))) { continue; } } // Reference to invalid character which is returned refInvalidChar = new Character(ch); return false; } } } // version of the document is XML 1.0 else { // we need to check all characters as per production rules of XML 1.0 int i = 0; while (i < datalength) { if (XMLChar.isInvalid(dataarray[i++])) { // check if this is a supplemental character char ch = dataarray[i - 1]; if (XMLChar.isHighSurrogate(ch) && i < datalength) { char ch2 = dataarray[i++]; if (XMLChar.isLowSurrogate(ch2) && XMLChar.isSupplemental( XMLChar.supplemental(ch, ch2))) { continue; } } // Reference to invalid character which is returned refInvalidChar = new Character(ch); return false; } } } // end-else fDocument.isXMLVersion() return true; } // isXMLCharWF
Checks if a XML character is well-formed. If there is a problem with the character a non-null Character is returned else null is returned.
Params:
  • characters – A String of characters to be checked for Well-Formedness
Returns:Character A reference to the character to be returned that was determined invalid.
/** * Checks if a XML character is well-formed. If there is a problem with * the character a non-null Character is returned else null is returned. * * @param characters A String of characters to be checked for Well-Formedness * @return Character A reference to the character to be returned that was determined invalid. */
protected Character isWFXMLChar(String chardata) { Character refInvalidChar; if (chardata == null || (chardata.length() == 0)) { return null; } char[] dataarray = chardata.toCharArray(); int datalength = dataarray.length; // version of the document is XML 1.1 if (fIsXMLVersion11) { //we need to check all characters as per production rules of XML11 int i = 0; while (i < datalength) { if (XML11Char.isXML11Invalid(dataarray[i++])) { // check if this is a supplemental character char ch = dataarray[i - 1]; if (XMLChar.isHighSurrogate(ch) && i < datalength) { char ch2 = dataarray[i++]; if (XMLChar.isLowSurrogate(ch2) && XMLChar.isSupplemental( XMLChar.supplemental(ch, ch2))) { continue; } } // Reference to invalid character which is returned refInvalidChar = new Character(ch); return refInvalidChar; } } } // version of the document is XML 1.0 else { // we need to check all characters as per production rules of XML 1.0 int i = 0; while (i < datalength) { if (XMLChar.isInvalid(dataarray[i++])) { // check if this is a supplemental character char ch = dataarray[i - 1]; if (XMLChar.isHighSurrogate(ch) && i < datalength) { char ch2 = dataarray[i++]; if (XMLChar.isLowSurrogate(ch2) && XMLChar.isSupplemental( XMLChar.supplemental(ch, ch2))) { continue; } } // Reference to invalid character which is returned refInvalidChar = new Character(ch); return refInvalidChar; } } } // end-else fDocument.isXMLVersion() return null; } // isXMLCharWF
Checks if a comment node is well-formed
Params:
  • data – The contents of the comment node
Returns:a boolean indiacating if the comment is well-formed or not.
/** * Checks if a comment node is well-formed * * @param data The contents of the comment node * @return a boolean indiacating if the comment is well-formed or not. */
protected void isCommentWellFormed(String data) { if (data == null || (data.length() == 0)) { return; } char[] dataarray = data.toCharArray(); int datalength = dataarray.length; // version of the document is XML 1.1 if (fIsXMLVersion11) { // we need to check all chracters as per production rules of XML11 int i = 0; while (i < datalength) { char c = dataarray[i++]; if (XML11Char.isXML11Invalid(c)) { // check if this is a supplemental character if (XMLChar.isHighSurrogate(c) && i < datalength) { char c2 = dataarray[i++]; if (XMLChar.isLowSurrogate(c2) && XMLChar.isSupplemental( XMLChar.supplemental(c, c2))) { continue; } } String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_COMMENT, new Object[] { new Character(c)}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER, null, null, null)); } } else if (c == '-' && i < datalength && dataarray[i] == '-') { String msg = Utils.messages.createMessage( MsgKey.ER_WF_DASH_IN_COMMENT, null); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER, null, null, null)); } } } } // version of the document is XML 1.0 else { // we need to check all chracters as per production rules of XML 1.0 int i = 0; while (i < datalength) { char c = dataarray[i++]; if (XMLChar.isInvalid(c)) { // check if this is a supplemental character if (XMLChar.isHighSurrogate(c) && i < datalength) { char c2 = dataarray[i++]; if (XMLChar.isLowSurrogate(c2) && XMLChar.isSupplemental( XMLChar.supplemental(c, c2))) { continue; } } String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_COMMENT, new Object[] { new Character(c)}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER, null, null, null)); } } else if (c == '-' && i < datalength && dataarray[i] == '-') { String msg = Utils.messages.createMessage( MsgKey.ER_WF_DASH_IN_COMMENT, null); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER, null, null, null)); } } } } return; }
Checks if an element node is well-formed, by checking its Name for well-formedness.
Params:
  • data – The contents of the comment node
Returns:a boolean indiacating if the comment is well-formed or not.
/** * Checks if an element node is well-formed, by checking its Name for well-formedness. * * @param data The contents of the comment node * @return a boolean indiacating if the comment is well-formed or not. */
protected void isElementWellFormed(Node node) { boolean isNameWF = false; if ((fFeatures & NAMESPACES) != 0) { isNameWF = isValidQName( node.getPrefix(), node.getLocalName(), fIsXMLVersion11); } else { isNameWF = isXMLName(node.getNodeName(), fIsXMLVersion11); } if (!isNameWF) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME, new Object[] { "Element", node.getNodeName()}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME, null, null, null)); } } }
Checks if an attr node is well-formed, by checking it's Name and value for well-formedness.
Params:
  • data – The contents of the comment node
Returns:a boolean indiacating if the comment is well-formed or not.
/** * Checks if an attr node is well-formed, by checking it's Name and value * for well-formedness. * * @param data The contents of the comment node * @return a boolean indiacating if the comment is well-formed or not. */
protected void isAttributeWellFormed(Node node) { boolean isNameWF = false; if ((fFeatures & NAMESPACES) != 0) { isNameWF = isValidQName( node.getPrefix(), node.getLocalName(), fIsXMLVersion11); } else { isNameWF = isXMLName(node.getNodeName(), fIsXMLVersion11); } if (!isNameWF) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME, new Object[] { "Attr", node.getNodeName()}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME, null, null, null)); } } // Check the Attr's node value // WFC: No < in Attribute Values String value = node.getNodeValue(); if (value.indexOf('<') >= 0) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_LT_IN_ATTVAL, new Object[] { ((Attr) node).getOwnerElement().getNodeName(), node.getNodeName()}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_LT_IN_ATTVAL, null, null, null)); } } // we need to loop through the children of attr nodes and check their values for // well-formedness NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); // An attribute node with no text or entity ref child for example // doc.createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:ns"); // followes by // element.setAttributeNodeNS(attribute); // can potentially lead to this situation. If the attribute // was a prefix Namespace attribute declaration then then DOM Core // should have some exception defined for this. if (child == null) { // we should probably report an error continue; } switch (child.getNodeType()) { case Node.TEXT_NODE : isTextWellFormed((Text) child); break; case Node.ENTITY_REFERENCE_NODE : isEntityReferneceWellFormed((EntityReference) child); break; default : } } // TODO: // WFC: Check if the attribute prefix is bound to // http://www.w3.org/2000/xmlns/ // WFC: Unique Att Spec // Perhaps pass a seen boolean value to this method. serializeAttList will determine // if the attr was seen before. }
Checks if a PI node is well-formed, by checking it's Name and data for well-formedness.
Params:
  • data – The contents of the comment node
/** * Checks if a PI node is well-formed, by checking it's Name and data * for well-formedness. * * @param data The contents of the comment node */
protected void isPIWellFormed(ProcessingInstruction node) { // Is the PI Target a valid XML name if (!isXMLName(node.getNodeName(), fIsXMLVersion11)) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME, new Object[] { "ProcessingInstruction", node.getTarget()}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME, null, null, null)); } } // Does the PI Data carry valid XML characters // REVISIT: Should we check if the PI DATA contains a ?> ??? Character invalidChar = isWFXMLChar(node.getData()); if (invalidChar != null) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_PI, new Object[] { Integer.toHexString(Character.getNumericValue(invalidChar.charValue())) }); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER, null, null, null)); } } }
Checks if an CDATASection node is well-formed, by checking it's data for well-formedness. Note that the presence of a CDATA termination mark in the contents of a CDATASection is handled by the parameter spli-cdata-sections
Params:
  • data – The contents of the comment node
/** * Checks if an CDATASection node is well-formed, by checking it's data * for well-formedness. Note that the presence of a CDATA termination mark * in the contents of a CDATASection is handled by the parameter * spli-cdata-sections * * @param data The contents of the comment node */
protected void isCDATASectionWellFormed(CDATASection node) { // Does the data valid XML character data Character invalidChar = isWFXMLChar(node.getData()); //if (!isWFXMLChar(node.getData(), invalidChar)) { if (invalidChar != null) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_CDATA, new Object[] { Integer.toHexString(Character.getNumericValue(invalidChar.charValue())) }); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER, null, null, null)); } } }
Checks if an Text node is well-formed, by checking if it contains invalid XML characters.
Params:
  • data – The contents of the comment node
/** * Checks if an Text node is well-formed, by checking if it contains invalid * XML characters. * * @param data The contents of the comment node */
protected void isTextWellFormed(Text node) { // Does the data valid XML character data Character invalidChar = isWFXMLChar(node.getData()); if (invalidChar != null) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_TEXT, new Object[] { Integer.toHexString(Character.getNumericValue(invalidChar.charValue())) }); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER, null, null, null)); } } }
Checks if an EntityRefernece node is well-formed, by checking it's node name. Then depending on whether it is referenced in Element content or in an Attr Node, checks if the EntityReference references an unparsed entity or a external entity and if so throws raises the appropriate well-formedness error.
Params:
  • data – The contents of the comment node
@parentThe parent of the EntityReference Node
/** * Checks if an EntityRefernece node is well-formed, by checking it's node name. Then depending * on whether it is referenced in Element content or in an Attr Node, checks if the EntityReference * references an unparsed entity or a external entity and if so throws raises the * appropriate well-formedness error. * * @param data The contents of the comment node * @parent The parent of the EntityReference Node */
protected void isEntityReferneceWellFormed(EntityReference node) { // Is the EntityReference name a valid XML name if (!isXMLName(node.getNodeName(), fIsXMLVersion11)) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME, new Object[] { "EntityReference", node.getNodeName()}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME, null, null, null)); } } // determine the parent node Node parent = node.getParentNode(); // Traverse the declared entities and check if the nodeName and namespaceURI // of the EntityReference matches an Entity. If so, check the if the notationName // is not null, if so, report an error. DocumentType docType = node.getOwnerDocument().getDoctype(); if (docType != null) { NamedNodeMap entities = docType.getEntities(); for (int i = 0; i < entities.getLength(); i++) { Entity ent = (Entity) entities.item(i); String nodeName = node.getNodeName() == null ? "" : node.getNodeName(); String nodeNamespaceURI = node.getNamespaceURI() == null ? "" : node.getNamespaceURI(); String entName = ent.getNodeName() == null ? "" : ent.getNodeName(); String entNamespaceURI = ent.getNamespaceURI() == null ? "" : ent.getNamespaceURI(); // If referenced in Element content // WFC: Parsed Entity if (parent.getNodeType() == Node.ELEMENT_NODE) { if (entNamespaceURI.equals(nodeNamespaceURI) && entName.equals(nodeName)) { if (ent.getNotationName() != null) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_REF_TO_UNPARSED_ENT, new Object[] { node.getNodeName()}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_REF_TO_UNPARSED_ENT, null, null, null)); } } } } // end if WFC: Parsed Entity // If referenced in an Attr value // WFC: No External Entity References if (parent.getNodeType() == Node.ATTRIBUTE_NODE) { if (entNamespaceURI.equals(nodeNamespaceURI) && entName.equals(nodeName)) { if (ent.getPublicId() != null || ent.getSystemId() != null || ent.getNotationName() != null) { String msg = Utils.messages.createMessage( MsgKey.ER_WF_REF_TO_EXTERNAL_ENT, new Object[] { node.getNodeName()}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_WF_REF_TO_EXTERNAL_ENT, null, null, null)); } } } } //end if WFC: No External Entity References } } } // isEntityReferneceWellFormed
If the configuration parameter "namespaces" is set to true, this methods checks if an entity whose replacement text contains unbound namespace prefixes is referenced in a location where there are no bindings for the namespace prefixes and if so raises a LSException with the error-type "unbound-prefix-in-entity-reference"
@paramNode, The EntityReference nodes whose children are to be checked
/** * If the configuration parameter "namespaces" is set to true, this methods * checks if an entity whose replacement text contains unbound namespace * prefixes is referenced in a location where there are no bindings for * the namespace prefixes and if so raises a LSException with the error-type * "unbound-prefix-in-entity-reference" * * @param Node, The EntityReference nodes whose children are to be checked */
protected void checkUnboundPrefixInEntRef(Node node) { Node child, next; for (child = node.getFirstChild(); child != null; child = next) { next = child.getNextSibling(); if (child.getNodeType() == Node.ELEMENT_NODE) { //If a NamespaceURI is not declared for the current //node's prefix, raise a fatal error. String prefix = child.getPrefix(); if (prefix != null && fNSBinder.getURI(prefix) == null) { String msg = Utils.messages.createMessage( MsgKey.ER_ELEM_UNBOUND_PREFIX_IN_ENTREF, new Object[] { node.getNodeName(), child.getNodeName(), prefix }); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_ELEM_UNBOUND_PREFIX_IN_ENTREF, null, null, null)); } } NamedNodeMap attrs = child.getAttributes(); for (int i = 0; i < attrs.getLength(); i++) { String attrPrefix = attrs.item(i).getPrefix(); if (attrPrefix != null && fNSBinder.getURI(attrPrefix) == null) { String msg = Utils.messages.createMessage( MsgKey.ER_ATTR_UNBOUND_PREFIX_IN_ENTREF, new Object[] { node.getNodeName(), child.getNodeName(), attrs.item(i)}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_FATAL_ERROR, msg, MsgKey.ER_ATTR_UNBOUND_PREFIX_IN_ENTREF, null, null, null)); } } } } if (child.hasChildNodes()) { checkUnboundPrefixInEntRef(child); } } } // *********************************************************************** // Namespace normalization // ***********************************************************************
Records local namespace declarations, to be used for normalization later
@paramNode, The element node, whose namespace declarations are to be recorded
/** * Records local namespace declarations, to be used for normalization later * * @param Node, The element node, whose namespace declarations are to be recorded */
protected void recordLocalNSDecl(Node node) { NamedNodeMap atts = ((Element) node).getAttributes(); int length = atts.getLength(); for (int i = 0; i < length; i++) { Node attr = atts.item(i); String localName = attr.getLocalName(); String attrPrefix = attr.getPrefix(); String attrValue = attr.getNodeValue(); String attrNS = attr.getNamespaceURI(); localName = localName == null || XMLNS_PREFIX.equals(localName) ? "" : localName; attrPrefix = attrPrefix == null ? "" : attrPrefix; attrValue = attrValue == null ? "" : attrValue; attrNS = attrNS == null ? "" : attrNS; // check if attribute is a namespace decl if (XMLNS_URI.equals(attrNS)) { // No prefix may be bound to http://www.w3.org/2000/xmlns/. if (XMLNS_URI.equals(attrValue)) { String msg = Utils.messages.createMessage( MsgKey.ER_NS_PREFIX_CANNOT_BE_BOUND, new Object[] { attrPrefix, XMLNS_URI }); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_ERROR, msg, MsgKey.ER_NS_PREFIX_CANNOT_BE_BOUND, null, null, null)); } } else { // store the namespace-declaration if (XMLNS_PREFIX.equals(attrPrefix) ) { // record valid decl if (attrValue.length() != 0) { fNSBinder.declarePrefix(localName, attrValue); } else { // Error; xmlns:prefix="" } } else { // xmlns // empty prefix is always bound ("" or some string) fNSBinder.declarePrefix("", attrValue); } } } } }
Fixes an element's namespace
@paramNode, The element node, whose namespace is to be fixed
/** * Fixes an element's namespace * * @param Node, The element node, whose namespace is to be fixed */
protected void fixupElementNS(Node node) throws SAXException { String namespaceURI = ((Element) node).getNamespaceURI(); String prefix = ((Element) node).getPrefix(); String localName = ((Element) node).getLocalName(); if (namespaceURI != null) { //if ( Element's prefix/namespace pair (or default namespace, // if no prefix) are within the scope of a binding ) prefix = prefix == null ? "" : prefix; String inScopeNamespaceURI = fNSBinder.getURI(prefix); if ((inScopeNamespaceURI != null && inScopeNamespaceURI.equals(namespaceURI))) { // do nothing, declaration in scope is inherited } else { // Create a local namespace declaration attr for this namespace, // with Element's current prefix (or a default namespace, if // no prefix). If there's a conflicting local declaration // already present, change its value to use this namespace. // Add the xmlns declaration attribute //fNSBinder.pushNamespace(prefix, namespaceURI, fElementDepth); if ((fFeatures & NAMESPACEDECLS) != 0) { if ("".equals(prefix) || "".equals(namespaceURI)) { ((Element)node).setAttributeNS(XMLNS_URI, XMLNS_PREFIX, namespaceURI); } else { ((Element)node).setAttributeNS(XMLNS_URI, XMLNS_PREFIX + ":" + prefix, namespaceURI); } } fLocalNSBinder.declarePrefix(prefix, namespaceURI); fNSBinder.declarePrefix(prefix, namespaceURI); } } else { // Element has no namespace // DOM Level 1 if (localName == null || "".equals(localName)) { // DOM Level 1 node! String msg = Utils.messages.createMessage( MsgKey.ER_NULL_LOCAL_ELEMENT_NAME, new Object[] { node.getNodeName()}); if (fErrorHandler != null) { fErrorHandler.handleError( new DOMErrorImpl( DOMError.SEVERITY_ERROR, msg, MsgKey.ER_NULL_LOCAL_ELEMENT_NAME, null, null, null)); } } else { namespaceURI = fNSBinder.getURI(""); if (namespaceURI !=null && namespaceURI.length() > 0) { ((Element)node).setAttributeNS(XMLNS_URI, XMLNS_PREFIX, ""); fLocalNSBinder.declarePrefix("", ""); fNSBinder.declarePrefix("", ""); } } } }
This table is a quick lookup of a property key (String) to the integer that is the bit to flip in the fFeatures field, so the integers should have values 1,2,4,8,16...
/** * This table is a quick lookup of a property key (String) to the integer that * is the bit to flip in the fFeatures field, so the integers should have * values 1,2,4,8,16... * */
private static final Map<String, Integer> fFeatureMap; static { // Initialize the mappings of property keys to bit values (Integer objects) // or mappings to a String object "", which indicates we are interested // in the property, but it does not have a simple bit value to flip Map<String, Integer> featureMap = new HashMap<>(); // cdata-sections featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_CDATA_SECTIONS, CDATA); // comments featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_COMMENTS, COMMENTS); // element-content-whitespace featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE, ELEM_CONTENT_WHITESPACE); // entities featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_ENTITIES, ENTITIES); // namespaces featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_NAMESPACES, NAMESPACES); // namespace-declarations featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_NAMESPACE_DECLARATIONS, NAMESPACEDECLS); // split-cdata-sections featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_SPLIT_CDATA, SPLITCDATA); // discard-default-content featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_WELLFORMED, WELLFORMED); // discard-default-content featureMap.put( DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_DISCARD_DEFAULT_CONTENT, DISCARDDEFAULT); fFeatureMap = Collections.unmodifiableMap(featureMap); }
Initializes fFeatures based on the DOMConfiguration Parameters set.
Params:
  • properties – DOMConfiguraiton properties that were set and which are to be used while serializing the DOM.
/** * Initializes fFeatures based on the DOMConfiguration Parameters set. * * @param properties DOMConfiguraiton properties that were set and which are * to be used while serializing the DOM. */
protected void initProperties(Properties properties) { for (Enumeration keys = properties.keys(); keys.hasMoreElements();) { final String key = (String) keys.nextElement(); // caonical-form // Other features will be enabled or disabled when this is set to true or false. // error-handler; set via the constructor // infoset // Other features will be enabled or disabled when this is set to true // A quick lookup for the given set of properties (cdata-sections ...) final Integer bitFlag = fFeatureMap.get(key); if (bitFlag != null) { // Dealing with a property that has a simple bit value that // we need to set // cdata-sections // comments // element-content-whitespace // entities // namespaces // namespace-declarations // split-cdata-sections // well-formed // discard-default-content if ((properties.getProperty(key).endsWith("yes"))) { fFeatures = fFeatures | bitFlag; } else { fFeatures = fFeatures & ~bitFlag; } } else { /** * Other properties that have a bit more complex value * than the features in the above map. */ if ((DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_FORMAT_PRETTY_PRINT) .equals(key)) { // format-pretty-print; set internally on the serializers via xsl:output properties in LSSerializer if ((properties.getProperty(key).endsWith("yes"))) { fSerializer.setIndent(true); fSerializer.setIndentAmount(4); } else { fSerializer.setIndent(false); } } else if ((DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL).equals(key)) { // omit-xml-declaration; set internally on the serializers via xsl:output properties in LSSerializer if ((properties.getProperty(key).endsWith("yes"))) { fSerializer.setOmitXMLDeclaration(true); } else { fSerializer.setOmitXMLDeclaration(false); } } else if ((DOMConstants.S_XERCES_PROPERTIES_NS + DOMConstants.S_XML_VERSION).equals(key)) { // Retreive the value of the XML Version attribute via the xml-version String version = properties.getProperty(key); if ("1.1".equals(version)) { fIsXMLVersion11 = true; fSerializer.setVersion(version); } else { fSerializer.setVersion("1.0"); } } else if ((DOMConstants.S_XSL_OUTPUT_ENCODING).equals(key)) { // Retreive the value of the XML Encoding attribute String encoding = properties.getProperty(key); if (encoding != null) { fSerializer.setEncoding(encoding); } } else if ((OutputPropertiesFactory.S_KEY_ENTITIES).equals(key)) { // Retreive the value of the XML Encoding attribute String entities = properties.getProperty(key); if (DOMConstants.S_XSL_VALUE_ENTITIES.equals(entities)) { fSerializer.setDTDEntityExpansion(false); } } } } // Set the newLine character to use if (fNewLine != null) { fSerializer.setOutputProperty(OutputPropertiesFactory.S_KEY_LINE_SEPARATOR, fNewLine); } } } //TreeWalker