mrglavas 2005/05/22 13:08:08
Added: java/src/org/apache/xerces/jaxp/validation
DOMResultBuilder.java DOMDocumentHandler.java
DOMValidatorHelper.java DOMResultAugmentor.java
Log:
DOM validation support.
In the RI this was achieved using identity transformers.
Here we go directly from DOM to XNI and back
instead of the intermediate SAX step. In addition to eliminating
the dependency on a transformer this gives us better performance.
We do a non-recursive walk of the DOM to prevent a stack overflow
for DOM's with high depth.
It should also be noted that the result builder will fill in PSVI and
DOM TypeInfo if the result node comes from the Xerces' DOM
implementation.
Revision Changes Path
1.1
xml-xerces/java/src/org/apache/xerces/jaxp/validation/DOMResultBuilder.java
Index: DOMResultBuilder.java
===================================================================
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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 org.apache.xerces.jaxp.validation;
import java.util.ArrayList;
import javax.xml.transform.dom.DOMResult;
import org.apache.xerces.dom.AttrImpl;
import org.apache.xerces.dom.CoreDocumentImpl;
import org.apache.xerces.dom.DOMMessageFormatter;
import org.apache.xerces.dom.DocumentTypeImpl;
import org.apache.xerces.dom.ElementImpl;
import org.apache.xerces.dom.ElementNSImpl;
import org.apache.xerces.dom.EntityImpl;
import org.apache.xerces.dom.NotationImpl;
import org.apache.xerces.dom.PSVIAttrNSImpl;
import org.apache.xerces.dom.PSVIDocumentImpl;
import org.apache.xerces.dom.PSVIElementNSImpl;
import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLDocumentSource;
import org.apache.xerces.xs.AttributePSVI;
import org.apache.xerces.xs.ElementPSVI;
import org.apache.xerces.xs.XSTypeDefinition;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Notation;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
/**
* <p>DOM result builder.</p>
*
* @author Michael Glavassevich, IBM
* @version $Id: DOMResultBuilder.java,v 1.1 2005/05/22 20:08:07 mrglavas Exp
$
*/
final class DOMResultBuilder implements DOMDocumentHandler {
/** Table for quick check of child insertion. */
private final static int[] kidOK;
static {
kidOK = new int[13];
kidOK[Node.DOCUMENT_NODE] =
1 << Node.ELEMENT_NODE | 1 << Node.PROCESSING_INSTRUCTION_NODE |
1 << Node.COMMENT_NODE | 1 << Node.DOCUMENT_TYPE_NODE;
kidOK[Node.DOCUMENT_FRAGMENT_NODE] =
kidOK[Node.ENTITY_NODE] =
kidOK[Node.ENTITY_REFERENCE_NODE] =
kidOK[Node.ELEMENT_NODE] =
1 << Node.ELEMENT_NODE | 1 << Node.PROCESSING_INSTRUCTION_NODE |
1 << Node.COMMENT_NODE | 1 << Node.TEXT_NODE |
1 << Node.CDATA_SECTION_NODE | 1 << Node.ENTITY_REFERENCE_NODE ;
kidOK[Node.ATTRIBUTE_NODE] = 1 << Node.TEXT_NODE | 1 <<
Node.ENTITY_REFERENCE_NODE;
kidOK[Node.DOCUMENT_TYPE_NODE] = 0;
kidOK[Node.PROCESSING_INSTRUCTION_NODE] = 0;
kidOK[Node.COMMENT_NODE] = 0;
kidOK[Node.TEXT_NODE] = 0;
kidOK[Node.CDATA_SECTION_NODE] = 0;
kidOK[Node.NOTATION_NODE] = 0;
} // static
//
// Data
//
private Document fDocument;
private CoreDocumentImpl fDocumentImpl;
private boolean fStorePSVI;
private Node fTarget;
private Node fNextSibling;
private Node fCurrentNode;
private Node fFragmentRoot;
private final ArrayList fTargetChildren = new ArrayList();
private boolean fIgnoreChars;
private final QName fAttributeQName = new QName();
public DOMResultBuilder() {}
/*
* DOMDocumentHandler methods
*/
public void setDOMResult(DOMResult result) {
fCurrentNode = null;
fFragmentRoot = null;
fIgnoreChars = false;
fTargetChildren.clear();
if (result != null) {
fTarget = result.getNode();
fNextSibling = result.getNextSibling();
fDocument = (fTarget.getNodeType() == Node.DOCUMENT_NODE) ?
(Document) fTarget : fTarget.getOwnerDocument();
fDocumentImpl = (fDocument instanceof CoreDocumentImpl) ?
(CoreDocumentImpl) fDocument : null;
fStorePSVI = (fDocument instanceof PSVIDocumentImpl);
return;
}
fTarget = null;
fNextSibling = null;
fDocument = null;
fDocumentImpl = null;
fStorePSVI = false;
}
public void doctypeDecl(DocumentType node) throws XNIException {
/** Create new DocumentType node for the target. */
if (fDocumentImpl != null) {
DocumentType docType =
fDocumentImpl.createDocumentType(node.getName(), node.getPublicId(),
node.getSystemId());
final String internalSubset = node.getInternalSubset();
/** Copy internal subset. */
if (internalSubset != null) {
((DocumentTypeImpl)
docType).setInternalSubset(internalSubset);
}
/** Copy entities. */
NamedNodeMap oldMap = node.getEntities();
NamedNodeMap newMap = docType.getEntities();
int length = oldMap.getLength();
for (int i = 0; i < length; ++i) {
Entity oldEntity = (Entity) oldMap.item(i);
EntityImpl newEntity = (EntityImpl)
fDocumentImpl.createEntity(oldEntity.getNodeName());
newEntity.setPublicId(oldEntity.getPublicId());
newEntity.setSystemId(oldEntity.getSystemId());
newEntity.setNotationName(oldEntity.getNotationName());
newMap.setNamedItem(newEntity);
}
/** Copy notations. */
oldMap = node.getNotations();
newMap = docType.getNotations();
length = oldMap.getLength();
for (int i = 0; i < length; ++i) {
Notation oldNotation = (Notation) oldMap.item(i);
NotationImpl newNotation = (NotationImpl)
fDocumentImpl.createNotation(oldNotation.getNodeName());
newNotation.setPublicId(oldNotation.getPublicId());
newNotation.setSystemId(oldNotation.getSystemId());
newMap.setNamedItem(newNotation);
}
append(docType);
}
}
public void characters(Text node) throws XNIException {
/** Create new Text node for the target. */
append(fDocument.createTextNode(node.getNodeValue()));
}
public void cdata(CDATASection node) throws XNIException {
/** Create new CDATASection node for the target. */
append(fDocument.createCDATASection(node.getNodeValue()));
}
public void comment(Comment node) throws XNIException {
/** Create new Comment node for the target. */
append(fDocument.createComment(node.getNodeValue()));
}
public void processingInstruction(ProcessingInstruction node)
throws XNIException {
/** Create new ProcessingInstruction node for the target. */
append(fDocument.createProcessingInstruction(node.getTarget(),
node.getData()));
}
public void setIgnoringCharacters(boolean ignore) {
fIgnoreChars = ignore;
}
/*
* XMLDocumentHandler methods
*/
public void startDocument(XMLLocator locator, String encoding,
NamespaceContext namespaceContext, Augmentations augs)
throws XNIException {}
public void xmlDecl(String version, String encoding, String standalone,
Augmentations augs) throws XNIException {}
public void doctypeDecl(String rootElement, String publicId,
String systemId, Augmentations augs) throws XNIException {}
public void comment(XMLString text, Augmentations augs) throws
XNIException {}
public void processingInstruction(String target, XMLString data,
Augmentations augs) throws XNIException {}
public void startElement(QName element, XMLAttributes attributes,
Augmentations augs) throws XNIException {
Element elem;
int attrCount = attributes.getLength();
if (fDocumentImpl == null) {
elem = fDocument.createElementNS(element.uri, element.rawname);
for (int i = 0; i < attrCount; ++i) {
attributes.getName(i, fAttributeQName);
elem.setAttributeNS(fAttributeQName.uri,
fAttributeQName.rawname, attributes.getValue(i));
}
}
// If it's a Xerces DOM store type information for attributes, set
idness, etc..
else {
elem = fDocumentImpl.createElementNS(element.uri,
element.rawname, element.localpart);
for (int i = 0; i < attrCount; ++i) {
attributes.getName(i, fAttributeQName);
AttrImpl attr = (AttrImpl)
fDocumentImpl.createAttributeNS(fAttributeQName.uri,
fAttributeQName.rawname, fAttributeQName.localpart);
attr.setValue(attributes.getValue(i));
// write type information to this attribute
AttributePSVI attrPSVI = (AttributePSVI)
attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_PSVI);
if (attrPSVI != null) {
if (fStorePSVI) {
((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
}
Object type = attrPSVI.getMemberTypeDefinition();
if (type == null) {
type = attrPSVI.getTypeDefinition();
if (type != null) {
attr.setType (type);
if (((XSSimpleType) type).isIDType()) {
((ElementImpl) elem).setIdAttributeNode
(attr, true);
}
}
}
else {
attr.setType (type);
if (((XSSimpleType) type).isIDType()) {
((ElementImpl) elem).setIdAttributeNode (attr,
true);
}
}
}
attr.setSpecified(attributes.isSpecified(i));
elem.setAttributeNode(attr);
}
}
append(elem);
fCurrentNode = elem;
if (fFragmentRoot == null) {
fFragmentRoot = elem;
}
}
public void emptyElement(QName element, XMLAttributes attributes,
Augmentations augs) throws XNIException {
startElement(element, attributes, augs);
endElement(element, augs);
}
public void startGeneralEntity(String name,
XMLResourceIdentifier identifier, String encoding,
Augmentations augs) throws XNIException {}
public void textDecl(String version, String encoding, Augmentations augs)
throws XNIException {}
public void endGeneralEntity(String name, Augmentations augs)
throws XNIException {}
public void characters(XMLString text, Augmentations augs)
throws XNIException {
if (!fIgnoreChars) {
append(fDocument.createTextNode(text.toString()));
}
}
public void ignorableWhitespace(XMLString text, Augmentations augs)
throws XNIException {
characters(text, augs);
}
public void endElement(QName element, Augmentations augs)
throws XNIException {
// write type information to this element
if (augs != null && fDocumentImpl != null) {
ElementPSVI elementPSVI =
(ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
if (elementPSVI != null) {
if (fStorePSVI) {
((PSVIElementNSImpl)fCurrentNode).setPSVI(elementPSVI);
}
XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
if (type == null) {
type = elementPSVI.getTypeDefinition();
}
((ElementNSImpl)fCurrentNode).setType(type);
}
}
// adjust current node reference
if (fCurrentNode == fFragmentRoot) {
fCurrentNode = null;
fFragmentRoot = null;
return;
}
fCurrentNode = fCurrentNode.getParentNode();
}
public void startCDATA(Augmentations augs) throws XNIException {}
public void endCDATA(Augmentations augs) throws XNIException {}
public void endDocument(Augmentations augs) throws XNIException {
final int length = fTargetChildren.size();
if (fNextSibling == null) {
for (int i = 0; i < length; ++i) {
fTarget.appendChild((Node) fTargetChildren.get(i));
}
}
else {
for (int i = 0; i < length; ++i) {
fTarget.insertBefore((Node) fTargetChildren.get(i),
fNextSibling);
}
}
}
public void setDocumentSource(XMLDocumentSource source) {}
public XMLDocumentSource getDocumentSource() {
return null;
}
/*
* Other methods
*/
private void append(Node node) throws XNIException {
if (fCurrentNode != null) {
fCurrentNode.appendChild(node);
}
else {
/** Check if this node can be attached to the target. */
if ((kidOK[fTarget.getNodeType()] & (1 << node.getNodeType())) ==
0) {
String msg =
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
"HIERARCHY_REQUEST_ERR", null);
throw new XNIException(msg);
}
fTargetChildren.add(node);
}
}
} // DOMResultBuilder
1.1
xml-xerces/java/src/org/apache/xerces/jaxp/validation/DOMDocumentHandler.java
Index: DOMDocumentHandler.java
===================================================================
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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 org.apache.xerces.jaxp.validation;
import javax.xml.transform.dom.DOMResult;
import org.apache.xerces.xni.XMLDocumentHandler;
import org.apache.xerces.xni.XNIException;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
/**
* <p>An extension to XMLDocumentHandler for building DOM structures.</p>
*
* @author Michael Glavassevich, IBM
* @version $Id: DOMDocumentHandler.java,v 1.1 2005/05/22 20:08:07 mrglavas
Exp $
*/
interface DOMDocumentHandler extends XMLDocumentHandler {
/**
* <p>Sets the <code>DOMResult</code> object which
* receives the constructed DOM nodes.</p>
*
* @param result the object which receives the constructed DOM nodes
*/
public void setDOMResult(DOMResult result);
/**
* A document type declaration.
*
* @param node a DocumentType node
*
* @exception XNIException Thrown by handler to signal an error.
*/
public void doctypeDecl(DocumentType node) throws XNIException;
public void characters(Text node) throws XNIException;
public void cdata(CDATASection node) throws XNIException;
/**
* A comment.
*
* @param node a Comment node
*
* @exception XNIException Thrown by application to signal an error.
*/
public void comment(Comment node) throws XNIException;
/**
* A processing instruction. Processing instructions consist of a
* target name and, optionally, text data. The data is only meaningful
* to the application.
* <p>
* Typically, a processing instruction's data will contain a series
* of pseudo-attributes. These pseudo-attributes follow the form of
* element attributes but are <strong>not</strong> parsed or presented
* to the application as anything other than text. The application is
* responsible for parsing the data.
*
* @param node a ProcessingInstruction node
*
* @exception XNIException Thrown by handler to signal an error.
*/
public void processingInstruction(ProcessingInstruction node) throws
XNIException;
public void setIgnoringCharacters(boolean ignore);
}
1.1
xml-xerces/java/src/org/apache/xerces/jaxp/validation/DOMValidatorHelper.java
Index: DOMValidatorHelper.java
===================================================================
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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 org.apache.xerces.jaxp.validation;
import java.io.IOException;
import java.util.Locale;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.impl.validation.EntityState;
import org.apache.xerces.impl.validation.ValidationManager;
import org.apache.xerces.impl.xs.util.SimpleLocator;
import org.apache.xerces.util.SymbolTable;
import org.apache.xerces.util.XMLAttributesImpl;
import org.apache.xerces.util.XMLSymbols;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLParseException;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Entity;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
/**
* <p>A validator helper for <code>DOMSource</code>s.</p>
*
* @author Michael Glavassevich, IBM
* @version $Id: DOMValidatorHelper.java,v 1.1 2005/05/22 20:08:07 mrglavas
Exp $
*/
final class DOMValidatorHelper implements ValidatorHelper, EntityState {
//
// Constants
//
/** Chunk size (1024). */
private static final int CHUNK_SIZE = (1 << 10);
/** Chunk mask (CHUNK_SIZE - 1). */
private static final int CHUNK_MASK = CHUNK_SIZE - 1;
// property identifiers
/** Property identifier: error reporter. */
private static final String ERROR_REPORTER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
/** Property identifier: namespace context. */
private static final String NAMESPACE_CONTEXT =
Constants.XERCES_PROPERTY_PREFIX +
Constants.NAMESPACE_CONTEXT_PROPERTY;
/** Property identifier: XML Schema validator. */
private static final String SCHEMA_VALIDATOR =
Constants.XERCES_PROPERTY_PREFIX +
Constants.SCHEMA_VALIDATOR_PROPERTY;
/** Property identifier: symbol table. */
private static final String SYMBOL_TABLE =
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
/** Property identifier: validation manager. */
private static final String VALIDATION_MANAGER =
Constants.XERCES_PROPERTY_PREFIX +
Constants.VALIDATION_MANAGER_PROPERTY;
//
// Data
//
/** Error reporter. */
private XMLErrorReporter fErrorReporter;
/** The namespace context of this document: stores namespaces in scope.
**/
private NamespaceContext fNamespaceContext;
/** Schema validator. **/
private org.apache.xerces.impl.xs.XMLSchemaValidator fSchemaValidator;
/** Symbol table **/
private SymbolTable fSymbolTable;
/** Validation manager. **/
private ValidationManager fValidationManager;
/** Component manager. **/
private XMLSchemaValidatorComponentManager fComponentManager;
/** REVISIT: Dummy locator object for DOM. **/
private final XMLLocator fXMLLocator = new SimpleLocator(null, null, -1,
-1, -1);
/** DOM document handler. **/
private DOMDocumentHandler fDOMValidatorHandler;
/** DOM result augmentor. **/
private final DOMResultAugmentor fDOMResultAugmentor = new
DOMResultAugmentor(this);
/** DOM result builder. **/
private final DOMResultBuilder fDOMResultBuilder = new DOMResultBuilder();
/** Map for tracking unparsed entities. **/
private NamedNodeMap fEntities = null;
/** Array for holding character data. **/
private char [] fCharBuffer = new char[CHUNK_SIZE];
/** Current element. **/
private Node fCurrentElement;
/** Fields for start element, end element and characters. **/
final QName fElementQName = new QName();
final QName fAttributeQName = new QName();
final XMLAttributesImpl fAttributes = new XMLAttributesImpl();
final XMLString fTempString = new XMLString();
public DOMValidatorHelper(XMLSchemaValidatorComponentManager
componentManager) {
fComponentManager = componentManager;
fErrorReporter = (XMLErrorReporter)
fComponentManager.getProperty(ERROR_REPORTER);
fNamespaceContext = (NamespaceContext)
fComponentManager.getProperty(NAMESPACE_CONTEXT);
fSchemaValidator = (org.apache.xerces.impl.xs.XMLSchemaValidator)
fComponentManager.getProperty(SCHEMA_VALIDATOR);
fSymbolTable = (SymbolTable)
fComponentManager.getProperty(SYMBOL_TABLE);
fValidationManager = (ValidationManager)
fComponentManager.getProperty(VALIDATION_MANAGER);
}
/*
* ValidatorHelper methods
*/
public void validate(Source source, Result result)
throws SAXException, IOException {
if (result instanceof DOMResult || result == null) {
final DOMSource domSource = (DOMSource) source;
final DOMResult domResult = (DOMResult) result;
Node node = domSource.getNode();
if (node != null) {
fComponentManager.reset();
fValidationManager.setEntityState(this);
fErrorReporter.setDocumentLocator(fXMLLocator);
try {
// regardless of what type of node this is, fire start
and end document events
setupEntityMap((node.getNodeType() == Node.DOCUMENT_NODE)
? (Document) node : node.getOwnerDocument());
setupDOMResultHandler(domSource, domResult);
fSchemaValidator.startDocument(fXMLLocator, null,
fNamespaceContext, null);
validate(node);
fSchemaValidator.endDocument(null);
}
catch (XMLParseException e) {
throw Util.toSAXParseException(e);
}
catch (XNIException e) {
throw Util.toSAXException(e);
}
finally {
// Release references to application objects
fCurrentElement = null;
fEntities = null;
if (fDOMValidatorHandler != null) {
fDOMValidatorHandler.setDOMResult(null);
}
}
}
return;
}
throw new
IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(Locale.getDefault(),
"SourceResultMismatch",
new Object [] {source.getClass().getName(),
result.getClass().getName()}));
}
/*
* EntityState methods
*/
public boolean isEntityDeclared(String name) {
return false;
}
public boolean isEntityUnparsed(String name) {
if (fEntities != null) {
Entity entity = (Entity) fEntities.getNamedItem(name);
if (entity != null) {
return (entity.getNotationName() != null);
}
}
return false;
}
/*
* Other methods
*/
/** Traverse the DOM and fire events to the schema validator. */
private void validate(Node node) {
final Node top = node;
// Performs a non-recursive traversal of the DOM. This
// will avoid a stack overflow for DOMs with high depth.
while (node != null) {
beginNode(node);
Node next = node.getFirstChild();
while (next == null) {
finishNode(node);
if (top == node) {
break;
}
next = node.getNextSibling();
if (next == null) {
node = node.getParentNode();
if (node == null || top == node) {
if (node != null) {
finishNode(node);
}
next = null;
break;
}
}
}
node = next;
}
}
/** Do processing for the start of a node. */
private void beginNode(Node node) {
switch (node.getNodeType()) {
case Node.ELEMENT_NODE:
fCurrentElement = node;
// push namespace context
fNamespaceContext.pushContext();
// start element
fillQName(fElementQName, node);
processAttributes(node.getAttributes());
fSchemaValidator.startElement(fElementQName, fAttributes,
null);
break;
case Node.TEXT_NODE:
if (fDOMValidatorHandler != null) {
fDOMValidatorHandler.setIgnoringCharacters(true);
sendCharactersToValidator(node.getNodeValue());
fDOMValidatorHandler.setIgnoringCharacters(false);
fDOMValidatorHandler.characters((Text) node);
}
else {
sendCharactersToValidator(node.getNodeValue());
}
break;
case Node.CDATA_SECTION_NODE:
if (fDOMValidatorHandler != null) {
fDOMValidatorHandler.setIgnoringCharacters(true);
fSchemaValidator.startCDATA(null);
sendCharactersToValidator(node.getNodeValue());
fSchemaValidator.endCDATA(null);
fDOMValidatorHandler.setIgnoringCharacters(false);
fDOMValidatorHandler.cdata((CDATASection) node);
}
else {
fSchemaValidator.startCDATA(null);
sendCharactersToValidator(node.getNodeValue());
fSchemaValidator.endCDATA(null);
}
break;
case Node.PROCESSING_INSTRUCTION_NODE:
/**
* The validator does nothing with processing instructions so
bypass it.
* Send the ProcessingInstruction node directly to the result
builder.
*/
if (fDOMValidatorHandler != null) {
fDOMValidatorHandler.processingInstruction((ProcessingInstruction) node);
}
break;
case Node.COMMENT_NODE:
/**
* The validator does nothing with comments so bypass it.
* Send the Comment node directly to the result builder.
*/
if (fDOMValidatorHandler != null) {
fDOMValidatorHandler.comment((Comment) node);
}
break;
case Node.DOCUMENT_TYPE_NODE:
/**
* Send the DocumentType node directly to the result builder.
*/
if (fDOMValidatorHandler != null) {
fDOMValidatorHandler.doctypeDecl((DocumentType) node);
}
break;
default: // Ignore other node types.
break;
}
}
/** Do processing for the end of a node. */
private void finishNode(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
fCurrentElement = node;
// end element
fillQName(fElementQName, node);
fSchemaValidator.endElement(fElementQName, null);
// pop namespace context
fNamespaceContext.popContext();
}
}
/**
* Extracts NamedNodeMap of entities. We need this to validate
* elements and attributes of type xs:ENTITY, xs:ENTITIES or
* types dervied from them.
*/
private void setupEntityMap(Document doc) {
if (doc != null) {
DocumentType docType = doc.getDoctype();
if (docType != null) {
fEntities = docType.getEntities();
return;
}
}
fEntities = null;
}
/**
* Sets up handler for <code>DOMResult</code>.
*/
private void setupDOMResultHandler(DOMSource source, DOMResult result)
throws SAXException {
// If there's no DOMResult, unset the validator handler
if (result == null) {
fDOMValidatorHandler = null;
fSchemaValidator.setDocumentHandler(null);
return;
}
final Node nodeResult = result.getNode();
// If the source node and result node are the same use the
DOMResultAugmentor.
// Otherwise use the DOMResultBuilder.
if (source.getNode() == nodeResult) {
fDOMValidatorHandler = fDOMResultAugmentor;
fDOMResultAugmentor.setDOMResult(result);
fSchemaValidator.setDocumentHandler(fDOMResultAugmentor);
return;
}
if (result.getNode() == null) {
try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
result.setNode(builder.newDocument());
}
catch (ParserConfigurationException e) {
throw new SAXException(e);
}
}
fDOMValidatorHandler = fDOMResultBuilder;
fDOMResultBuilder.setDOMResult(result);
fSchemaValidator.setDocumentHandler(fDOMResultBuilder);
}
private void fillQName(QName toFill, Node node) {
final String prefix = node.getPrefix();
final String localName = node.getLocalName();
final String rawName = node.getNodeName();
final String namespace = node.getNamespaceURI();
toFill.prefix = (prefix != null) ? fSymbolTable.addSymbol(prefix) :
XMLSymbols.EMPTY_STRING;
toFill.localpart = (localName != null) ?
fSymbolTable.addSymbol(localName) : XMLSymbols.EMPTY_STRING;
toFill.rawname = (rawName != null) ? fSymbolTable.addSymbol(rawName)
: XMLSymbols.EMPTY_STRING;
toFill.uri = (namespace != null && namespace.length() > 0) ?
fSymbolTable.addSymbol(namespace) : null;
}
private void processAttributes(NamedNodeMap attrMap) {
final int attrCount = attrMap.getLength();
fAttributes.removeAllAttributes();
for (int i = 0; i < attrCount; ++i) {
Attr attr = (Attr) attrMap.item(i);
String value = attr.getValue();
if (value == null) {
value = XMLSymbols.EMPTY_STRING;
}
fillQName(fAttributeQName, attr);
// REVISIT: Assuming all attributes are of type CDATA. The actual
type may not matter. -- mrglavas
fAttributes.addAttributeNS(fAttributeQName,
XMLSymbols.fCDATASymbol, value);
fAttributes.setSpecified(i, attr.getSpecified());
// REVISIT: Should we be looking at non-namespace attributes
// for additional mappings? Should we detect illegal namespace
// declarations and exclude them from the context? -- mrglavas
if (fAttributeQName.uri == NamespaceContext.XMLNS_URI) {
// process namespace attribute
if (fAttributeQName.prefix == XMLSymbols.PREFIX_XMLNS) {
fNamespaceContext.declarePrefix(fAttributeQName.localpart,
fSymbolTable.addSymbol(value));
}
else {
fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING,
fSymbolTable.addSymbol(value));
}
}
}
}
private void sendCharactersToValidator(String str) {
if (str != null) {
final int length = str.length();
final int remainder = length & CHUNK_MASK;
if (remainder > 0) {
str.getChars(0, remainder, fCharBuffer, 0);
fTempString.setValues(fCharBuffer, 0, remainder);
fSchemaValidator.characters(fTempString, null);
}
int i = remainder;
while (i < length) {
str.getChars(i, i += CHUNK_SIZE, fCharBuffer, 0);
fTempString.setValues(fCharBuffer, 0, CHUNK_SIZE);
fSchemaValidator.characters(fTempString, null);
}
}
}
Node getCurrentElement() {
return fCurrentElement;
}
} // DOMValidatorHelper
1.1
xml-xerces/java/src/org/apache/xerces/jaxp/validation/DOMResultAugmentor.java
Index: DOMResultAugmentor.java
===================================================================
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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 org.apache.xerces.jaxp.validation;
import javax.xml.transform.dom.DOMResult;
import org.apache.xerces.dom.AttrImpl;
import org.apache.xerces.dom.CoreDocumentImpl;
import org.apache.xerces.dom.ElementImpl;
import org.apache.xerces.dom.ElementNSImpl;
import org.apache.xerces.dom.PSVIAttrNSImpl;
import org.apache.xerces.dom.PSVIDocumentImpl;
import org.apache.xerces.dom.PSVIElementNSImpl;
import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLDocumentSource;
import org.apache.xerces.xs.AttributePSVI;
import org.apache.xerces.xs.ElementPSVI;
import org.apache.xerces.xs.XSTypeDefinition;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
/**
* <p>DOM result augmentor.</p>
*
* @author Michael Glavassevich, IBM
* @version $Id: DOMResultAugmentor.java,v 1.1 2005/05/22 20:08:07 mrglavas
Exp $
*/
final class DOMResultAugmentor implements DOMDocumentHandler {
//
// Data
//
private DOMValidatorHelper fDOMValidatorHelper;
private Document fDocument;
private CoreDocumentImpl fDocumentImpl;
private boolean fStorePSVI;
private boolean fIgnoreChars;
private final QName fAttributeQName = new QName();
public DOMResultAugmentor(DOMValidatorHelper helper) {
fDOMValidatorHelper = helper;
}
public void setDOMResult(DOMResult result) {
fIgnoreChars = false;
if (result != null) {
final Node target = result.getNode();
fDocument = (target.getNodeType() == Node.DOCUMENT_NODE) ?
(Document) target : target.getOwnerDocument();
fDocumentImpl = (fDocument instanceof CoreDocumentImpl) ?
(CoreDocumentImpl) fDocument : null;
fStorePSVI = (fDocument instanceof PSVIDocumentImpl);
return;
}
fDocument = null;
fDocumentImpl = null;
fStorePSVI = false;
}
public void doctypeDecl(DocumentType node) throws XNIException {}
public void characters(Text node) throws XNIException {}
public void cdata(CDATASection node) throws XNIException {}
public void comment(Comment node) throws XNIException {}
public void processingInstruction(ProcessingInstruction node)
throws XNIException {}
public void setIgnoringCharacters(boolean ignore) {
fIgnoreChars = ignore;
}
public void startDocument(XMLLocator locator, String encoding,
NamespaceContext namespaceContext, Augmentations augs)
throws XNIException {}
public void xmlDecl(String version, String encoding, String standalone,
Augmentations augs) throws XNIException {}
public void doctypeDecl(String rootElement, String publicId,
String systemId, Augmentations augs) throws XNIException {}
public void comment(XMLString text, Augmentations augs) throws
XNIException {}
public void processingInstruction(String target, XMLString data,
Augmentations augs) throws XNIException {}
public void startElement(QName element, XMLAttributes attributes,
Augmentations augs) throws XNIException {
final Element currentElement = (Element)
fDOMValidatorHelper.getCurrentElement();
final NamedNodeMap attrMap = currentElement.getAttributes();
final int oldLength = attrMap.getLength();
// If it's a Xerces DOM store type information for attributes, set
idness, etc..
if (fDocumentImpl != null) {
AttrImpl attr;
for (int i = 0; i < oldLength; ++i) {
attr = (AttrImpl) attrMap.item(i);
// write type information to this attribute
AttributePSVI attrPSVI = (AttributePSVI)
attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_PSVI);
if (attrPSVI != null) {
if (processAttributePSVI(attr, attrPSVI)) {
((ElementImpl) currentElement).setIdAttributeNode
(attr, true);
}
}
}
}
final int newLength = attributes.getLength();
// Add default/fixed attributes
if (newLength > oldLength) {
if (fDocumentImpl == null) {
for (int i = oldLength; i < newLength; ++i) {
attributes.getName(i, fAttributeQName);
currentElement.setAttributeNS(fAttributeQName.uri,
fAttributeQName.rawname, attributes.getValue(i));
}
}
// If it's a Xerces DOM store type information for attributes,
set idness, etc..
else {
for (int i = oldLength; i < newLength; ++i) {
attributes.getName(i, fAttributeQName);
AttrImpl attr = (AttrImpl)
fDocumentImpl.createAttributeNS(fAttributeQName.uri,
fAttributeQName.rawname,
fAttributeQName.localpart);
attr.setValue(attributes.getValue(i));
// write type information to this attribute
AttributePSVI attrPSVI = (AttributePSVI)
attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_PSVI);
if (attrPSVI != null) {
if (processAttributePSVI(attr, attrPSVI)) {
((ElementImpl) currentElement).setIdAttributeNode
(attr, true);
}
}
attr.setSpecified(false);
currentElement.setAttributeNode(attr);
}
}
}
}
public void emptyElement(QName element, XMLAttributes attributes,
Augmentations augs) throws XNIException {
startElement(element, attributes, augs);
endElement(element, augs);
}
public void startGeneralEntity(String name,
XMLResourceIdentifier identifier, String encoding,
Augmentations augs) throws XNIException {}
public void textDecl(String version, String encoding, Augmentations augs)
throws XNIException {}
public void endGeneralEntity(String name, Augmentations augs)
throws XNIException {}
public void characters(XMLString text, Augmentations augs)
throws XNIException {
if (!fIgnoreChars) {
final Element currentElement = (Element)
fDOMValidatorHelper.getCurrentElement();
currentElement.appendChild(fDocument.createTextNode(text.toString()));
}
}
public void ignorableWhitespace(XMLString text, Augmentations augs)
throws XNIException {
characters(text, augs);
}
public void endElement(QName element, Augmentations augs)
throws XNIException {
final Node currentElement = fDOMValidatorHelper.getCurrentElement();
// Write type information to this element
if (augs != null && fDocumentImpl != null) {
ElementPSVI elementPSVI =
(ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
if (elementPSVI != null) {
if (fStorePSVI) {
((PSVIElementNSImpl) currentElement).setPSVI(elementPSVI);
}
XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
if (type == null) {
type = elementPSVI.getTypeDefinition();
}
((ElementNSImpl) currentElement).setType(type);
}
}
}
public void startCDATA(Augmentations augs) throws XNIException {}
public void endCDATA(Augmentations augs) throws XNIException {}
public void endDocument(Augmentations augs) throws XNIException {}
public void setDocumentSource(XMLDocumentSource source) {}
public XMLDocumentSource getDocumentSource() {
return null;
}
/** Returns whether the given attribute is an ID type. **/
private boolean processAttributePSVI(AttrImpl attr, AttributePSVI
attrPSVI) {
if (fStorePSVI) {
((PSVIAttrNSImpl) attr).setPSVI (attrPSVI);
}
Object type = attrPSVI.getMemberTypeDefinition ();
if (type == null) {
type = attrPSVI.getTypeDefinition ();
if (type != null) {
attr.setType(type);
return ((XSSimpleType) type).isIDType();
}
}
else {
attr.setType(type);
return ((XSSimpleType) type).isIDType();
}
return false;
}
} // DOMResultAugmentor
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]