![JAR search and dependency download from the Maven repository](/logo.png)
org.odftoolkit.odfdom.pkg.OdfFileSaxHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of odfdom-java Show documentation
Show all versions of odfdom-java Show documentation
ODFDOM is an OpenDocument Format (ODF) framework. Its purpose
is to provide an easy common way to create, access and
manipulate ODF files, without requiring detailed knowledge of
the ODF specification. It is designed to provide the ODF
developer community with an easy lightwork programming API
portable to any object-oriented language.
The current reference implementation is written in Java.
/************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
*
* Use is subject to license terms.
*
* 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. You can also
* obtain a copy of the License at http://odftoolkit.org/docs/license.txt
*
* 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.odftoolkit.odfdom.pkg;
import java.io.IOException;
import java.util.Stack;
import org.odftoolkit.odfdom.pkg.rdfa.JenaSink;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class OdfFileSaxHandler extends DefaultHandler {
private static final String EMPTY_STRING = "";
// the empty XML file to which nodes will be added
private OdfFileDom mFileDom;
// the context node
private Node mNode; // a stack of sub handlers. handlers will be pushed on the stack whenever
// they are required and must pop themselves from the stack when done
private Stack mHandlerStack = new Stack();
private StringBuilder mCharsForTextNode = new StringBuilder();
private JenaSink sink;
OdfFileSaxHandler(Node rootNode) {
if (rootNode instanceof OdfFileDom) {
mFileDom = (OdfFileDom) rootNode;
} else {
mFileDom = (OdfFileDom) rootNode.getOwnerDocument();
}
mNode = rootNode;
}
@Override
public void startDocument() throws SAXException {
}
@Override
public void endDocument() throws SAXException {
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
flushTextNode();
// pop to the parent node
mNode = mNode.getParentNode();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
flushTextNode();
// if there is a specilized handler on the stack, dispatch the event
Element element = null;
if (uri.equals(EMPTY_STRING) || qName.equals(EMPTY_STRING)) {
element = mFileDom.createElement(localName);
} else {
element = mFileDom.createElementNS(uri, qName);
}
String attrQname = null;
String attrURL = null;
OdfAttribute attr = null;
for (int i = 0; i < attributes.getLength(); i++) {
attrURL = attributes.getURI(i);
attrQname = attributes.getQName(i);
// if no namespace exists
if (attrURL.equals(EMPTY_STRING) || attrQname.equals(EMPTY_STRING)) {
// create attribute without prefix
attr = mFileDom.createAttribute(attributes.getLocalName(i));
} else {
if (attrQname.startsWith("xmlns:")) {
// in case of xmlns prefix we have to create a new OdfNamespace
OdfNamespace namespace = mFileDom.setNamespace(attributes.getLocalName(i), attributes.getValue(i));
// if the file Dom is already associated to parsed XML add the new namespace to the root element
Element root = mFileDom.getRootElement();
if (root == null) {
root = element;
}
root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" + namespace.getPrefix(), namespace.getUri());
}
// create all attributes, even namespace attributes
attr = mFileDom.createAttributeNS(attrURL, attrQname);
}
// namespace attributes will not be created and return null
if (attr != null) {
element.setAttributeNodeNS(attr);
// don't exit because of invalid attribute values
try {
// set Value in the attribute to allow validation in the attribute
attr.setValue(attributes.getValue(i));
} // if we detect an attribute with invalid value: remove attribute node
catch (IllegalArgumentException e) {
element.removeAttributeNode(attr);
}
}
}
// add the new element as a child of the current context node
mNode.appendChild(element);
// push the new element as the context node...
mNode = element;
if (!localName.equals("bookmark-start")){
setContextNode(mNode);
}
}
/**
* http://xerces.apache.org/xerces2-j/faq-sax.html#faq-2 :
* SAX may deliver contiguous text as multiple calls to characters,
* for reasons having to do with parser efficiency and input buffering.
* It is the programmer's responsibility to deal with that appropriately,
* e.g. by accumulating text until the next non-characters event.
*/
private void flushTextNode() {
if (mCharsForTextNode.length() > 0) {
Text text = mFileDom.createTextNode(mCharsForTextNode.toString());
mNode.appendChild(text);
mCharsForTextNode.setLength(0);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (!mHandlerStack.empty()) {
mHandlerStack.peek().characters(ch, start, length);
} else {
mCharsForTextNode.append(ch, start, length);
}
}
@Override
public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
return super.resolveEntity(publicId, systemId);
}
/**
* Expose the current node to JenaSink to for caching the parsed RDF triples.
* @return
*/
private void setContextNode(Node node){
if (this.sink !=null){
sink.setContextNode(node);
}
}
/**
* Set the JenaSink object.
* @param sink
*/
public void setSink(JenaSink sink) {
this.sink = sink;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy