summaryrefslogtreecommitdiff
path: root/unoxml/source/dom/saxbuilder.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'unoxml/source/dom/saxbuilder.cxx')
-rw-r--r--unoxml/source/dom/saxbuilder.cxx383
1 files changed, 383 insertions, 0 deletions
diff --git a/unoxml/source/dom/saxbuilder.cxx b/unoxml/source/dom/saxbuilder.cxx
new file mode 100644
index 000000000000..6b73cbfb733f
--- /dev/null
+++ b/unoxml/source/dom/saxbuilder.cxx
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#if defined(_MSC_VER) && (_MSC_VER > 1310)
+#pragma warning(disable : 4701)
+#endif
+
+#include "saxbuilder.hxx"
+
+#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
+
+
+namespace DOM
+{
+ Reference< XInterface > CSAXDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr)
+ {
+ return static_cast< XSAXDocumentBuilder* >(new CSAXDocumentBuilder(rSMgr));
+ }
+
+ const char* CSAXDocumentBuilder::aImplementationName = "com.sun.star.comp.xml.dom.SAXDocumentBuilder";
+ const char* CSAXDocumentBuilder::aSupportedServiceNames[] = {
+ "com.sun.star.xml.dom.SAXDocumentBuilder",
+ NULL
+ };
+
+ CSAXDocumentBuilder::CSAXDocumentBuilder(const Reference< XMultiServiceFactory >& mgr)
+ : m_aServiceManager(mgr)
+ , m_aState( SAXDocumentBuilderState_READY)
+ {}
+
+ OUString CSAXDocumentBuilder::_getImplementationName()
+ {
+ return OUString::createFromAscii(aImplementationName);
+ }
+ Sequence<OUString> CSAXDocumentBuilder::_getSupportedServiceNames()
+ {
+ Sequence<OUString> aSequence;
+ for (int i=0; aSupportedServiceNames[i]!=NULL; i++) {
+ aSequence.realloc(i+1);
+ aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i]));
+ }
+ return aSequence;
+ }
+
+ Sequence< OUString > SAL_CALL CSAXDocumentBuilder::getSupportedServiceNames()
+ throw (RuntimeException)
+ {
+ return CSAXDocumentBuilder::_getSupportedServiceNames();
+ }
+
+ OUString SAL_CALL CSAXDocumentBuilder::getImplementationName()
+ throw (RuntimeException)
+ {
+ return CSAXDocumentBuilder::_getImplementationName();
+ }
+
+ sal_Bool SAL_CALL CSAXDocumentBuilder::supportsService(const OUString& aServiceName)
+ throw (RuntimeException)
+ {
+ Sequence< OUString > supported = CSAXDocumentBuilder::_getSupportedServiceNames();
+ for (sal_Int32 i=0; i<supported.getLength(); i++)
+ {
+ if (supported[i] == aServiceName) return sal_True;
+ }
+ return sal_False;
+ }
+
+
+ SAXDocumentBuilderState SAL_CALL CSAXDocumentBuilder::getState()
+ throw (RuntimeException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ return m_aState;
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::reset()
+ throw (RuntimeException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ m_aDocument = Reference< XDocument >();
+ m_aFragment = Reference< XDocumentFragment >();
+ while (!m_aNodeStack.empty()) m_aNodeStack.pop();
+ while (!m_aNSStack.empty()) m_aNSStack.pop();
+ m_aState = SAXDocumentBuilderState_READY;
+ }
+
+ Reference< XDocument > SAL_CALL CSAXDocumentBuilder::getDocument()
+ throw (RuntimeException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ if (m_aState != SAXDocumentBuilderState_DOCUMENT_FINISHED)
+ throw RuntimeException();
+
+ return m_aDocument;
+ }
+
+ Reference< XDocumentFragment > SAL_CALL CSAXDocumentBuilder::getDocumentFragment()
+ throw (RuntimeException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ if (m_aState != SAXDocumentBuilderState_FRAGMENT_FINISHED)
+ throw RuntimeException();
+ return m_aFragment;
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::startDocumentFragment(const Reference< XDocument >& ownerDoc)
+ throw (RuntimeException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // start a new document fragment and push it onto the stack
+ // we have to be in a clean state to do this
+ if (!m_aState == SAXDocumentBuilderState_READY)
+ throw RuntimeException();
+
+ m_aDocument = ownerDoc;
+ Reference< XDocumentFragment > aFragment = m_aDocument->createDocumentFragment();
+ m_aNodeStack.push(Reference< XNode >(aFragment, UNO_QUERY));
+ m_aFragment = aFragment;
+ m_aState = SAXDocumentBuilderState_BUILDING_FRAGMENT;
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::endDocumentFragment()
+ throw (RuntimeException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // there should only be the document left on the node stack
+ if (m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
+ throw RuntimeException();
+
+ Reference< XNode > aNode = m_aNodeStack.top();
+ if ( aNode->getNodeType() != NodeType_DOCUMENT_FRAGMENT_NODE)
+ throw RuntimeException();
+ m_aNodeStack.pop();
+ m_aState = SAXDocumentBuilderState_FRAGMENT_FINISHED;
+ }
+
+ // document handler
+
+ void SAL_CALL CSAXDocumentBuilder::startDocument() throw (RuntimeException, SAXException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // start a new document and push it onto the stack
+ // we have to be in a clean state to do this
+ if (!m_aState == SAXDocumentBuilderState_READY)
+ throw SAXException();
+
+ Reference< XDocumentBuilder > aBuilder(m_aServiceManager->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder"))), UNO_QUERY_THROW);
+ Reference< XDocument > aDocument = aBuilder->newDocument();
+ m_aNodeStack.push(Reference< XNode >(aDocument, UNO_QUERY));
+ m_aDocument = aDocument;
+ m_aState = SAXDocumentBuilderState_BUILDING_DOCUMENT;
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::endDocument() throw (RuntimeException, SAXException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // there should only be the document left on the node stack
+ if (!m_aState == SAXDocumentBuilderState_BUILDING_DOCUMENT)
+ throw SAXException();
+
+ Reference< XNode > aNode = m_aNodeStack.top();
+ if ( aNode->getNodeType() != NodeType_DOCUMENT_NODE)
+ throw SAXException();
+ m_aNodeStack.pop();
+ m_aState = SAXDocumentBuilderState_DOCUMENT_FINISHED;
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::startElement(const OUString& aName, const Reference< XAttributeList>& attribs)
+ throw (RuntimeException, SAXException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
+ m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
+ {
+ throw SAXException();
+ }
+
+ // start with mappings in effect for last level
+ NSMap aNSMap;
+ if (!m_aNSStack.empty())
+ aNSMap = NSMap(m_aNSStack.top());
+
+ // handle xmlns: attributes and add to mappings
+ OUString attr_qname;
+ OUString attr_value;
+ OUString newprefix;
+ AttrMap aAttrMap;
+ sal_Int32 idx=-1;
+ sal_Int16 nAttributes = attribs->getLength();
+ for (sal_Int16 i=0; i<nAttributes; i++)
+ {
+ attr_qname = attribs->getNameByIndex(i);
+ attr_value = attribs->getValueByIndex(i);
+ // new prefix mapping
+ if (attr_qname.indexOf(OUString(RTL_CONSTASCII_USTRINGPARAM("xmlns:"))) == 0)
+ {
+ newprefix = attr_qname.copy(attr_qname.indexOf(':')+1);
+ aNSMap.insert(NSMap::value_type(newprefix, attr_value));
+ }
+ else if (attr_qname == OUString(RTL_CONSTASCII_USTRINGPARAM("xmlns")))
+ {
+ // new default prefix
+ aNSMap.insert(NSMap::value_type(OUString(), attr_value));
+ }
+ else
+ {
+ aAttrMap.insert(AttrMap::value_type(attr_qname, attr_value));
+ }
+ }
+
+ // does the element have a prefix?
+ OUString aPrefix;
+ OUString aURI;
+ Reference< XElement > aElement;
+ idx = aName.indexOf(':');
+ if (idx != -1)
+ {
+ aPrefix = aName.copy(0, idx);
+ }
+ else
+ aPrefix = OUString();
+
+ NSMap::const_iterator result = aNSMap.find(aPrefix);
+ if ( result != aNSMap.end())
+ {
+ // found a URI for prefix
+ // qualified name
+ aElement = m_aDocument->createElementNS( result->second, aName);
+ }
+ else
+ {
+ // no URI for prefix
+ aElement = m_aDocument->createElement(aName);
+ }
+ aElement = Reference< XElement > (
+ m_aNodeStack.top()->appendChild(Reference< XNode >(aElement, UNO_QUERY)),
+ UNO_QUERY);
+ m_aNodeStack.push(Reference< XNode >(aElement, UNO_QUERY));
+
+ // set non xmlns attributes
+ aPrefix = OUString();
+ aURI = OUString();
+ AttrMap::const_iterator a = aAttrMap.begin();
+ while (a != aAttrMap.end())
+ {
+ attr_qname = a->first;
+ attr_value = a->second;
+ idx = attr_qname.indexOf(':');
+ if (idx != -1)
+ aPrefix = attr_qname.copy(0, idx);
+ else
+ aPrefix = OUString();
+
+ result = aNSMap.find(aPrefix);
+ if (result != aNSMap.end())
+ {
+ // set attribute with namespace
+ aElement->setAttributeNS(result->second, attr_qname, attr_value);
+ }
+ else
+ {
+ // set attribute without namespace
+ aElement->setAttribute(attr_qname, attr_value);
+ }
+ ++a;
+ }
+ m_aNSStack.push(aNSMap);
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::endElement(const OUString& aName)
+ throw (RuntimeException, SAXException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // pop the current element from the stack
+ if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
+ m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
+ throw SAXException();
+
+ Reference< XNode > aNode(m_aNodeStack.top());
+ if (aNode->getNodeType() != NodeType_ELEMENT_NODE)
+ throw SAXException();
+
+ Reference< XElement > aElement(aNode, UNO_QUERY);
+ OUString aRefName;
+ OUString aPrefix = aElement->getPrefix();
+ if (aPrefix.getLength() > 0)
+ aRefName = aPrefix + OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + aElement->getTagName();
+ else
+ aRefName = aElement->getTagName();
+ if (aRefName != aName) // consistency check
+ throw SAXException();
+
+ // pop it
+ m_aNodeStack.pop();
+ m_aNSStack.pop();
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::characters(const OUString& aChars)
+ throw (RuntimeException, SAXException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // append text node to the current top element
+ if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
+ m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
+ throw SAXException();
+
+ Reference< XText > aText = m_aDocument->createTextNode(aChars);
+ m_aNodeStack.top()->appendChild(Reference< XNode >(aText, UNO_QUERY));
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::ignorableWhitespace(const OUString& )
+ throw (RuntimeException, SAXException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // ignore ignorable whitespace
+ if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
+ m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
+ throw SAXException();
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::processingInstruction(const OUString& aTarget, const OUString& aData)
+ throw (RuntimeException, SAXException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // append PI node to the current top
+ if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT &&
+ m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT)
+ throw SAXException();
+
+ Reference< XProcessingInstruction > aInstruction = m_aDocument->createProcessingInstruction(
+ aTarget, aData);
+ m_aNodeStack.top()->appendChild(Reference< XNode >(aInstruction, UNO_QUERY));
+ }
+
+ void SAL_CALL CSAXDocumentBuilder::setDocumentLocator(const Reference< XLocator >& aLocator)
+ throw (RuntimeException, SAXException)
+ {
+ ::osl::MutexGuard g(m_Mutex);
+
+ // set the document locator...
+ m_aLocator = aLocator;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */