diff options
Diffstat (limited to 'unoxml/source/dom/document.cxx')
-rw-r--r-- | unoxml/source/dom/document.cxx | 713 |
1 files changed, 713 insertions, 0 deletions
diff --git a/unoxml/source/dom/document.cxx b/unoxml/source/dom/document.cxx new file mode 100644 index 000000000000..fcd43832adf0 --- /dev/null +++ b/unoxml/source/dom/document.cxx @@ -0,0 +1,713 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#include <com/sun/star/uno/Sequence.h> + +#include "document.hxx" +#include "attr.hxx" +#include "element.hxx" +#include "cdatasection.hxx" +#include "documentfragment.hxx" +#include "text.hxx" +#include "cdatasection.hxx" +#include "comment.hxx" +#include "processinginstruction.hxx" +#include "entityreference.hxx" +#include "documenttype.hxx" +#include "elementlist.hxx" +#include "domimplementation.hxx" + +#include "../events/event.hxx" +#include "../events/mutationevent.hxx" +#include "../events/uievent.hxx" +#include "../events/mouseevent.hxx" + +#include <string.h> + +#include <com/sun/star/xml/sax/FastToken.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + +namespace DOM +{ + CDocument::~CDocument() + { + xmlFreeDoc(m_aDocPtr); + } + + CDocument::CDocument(xmlDocPtr aDocPtr): + m_aDocPtr(aDocPtr), + m_streamListeners() + { + // init node base + m_aNodeType = NodeType_DOCUMENT_NODE; + init_node((xmlNodePtr)m_aDocPtr); + } + + void SAL_CALL CDocument::saxify( + const Reference< XDocumentHandler >& i_xHandler) { + i_xHandler->startDocument(); + for (xmlNodePtr pChild = m_aNodePtr->children; + pChild != 0; pChild = pChild->next) { + CNode * pNode = CNode::get(pChild); + OSL_ENSURE(pNode != 0, "CNode::get returned 0"); + pNode->saxify(i_xHandler); + } + i_xHandler->endDocument(); + } + + void SAL_CALL CDocument::fastSaxify( Context& rContext ) { + rContext.mxDocHandler->startDocument(); + for (xmlNodePtr pChild = m_aNodePtr->children; + pChild != 0; pChild = pChild->next) { + CNode * pNode = CNode::get(pChild); + OSL_ENSURE(pNode != 0, "CNode::get returned 0"); + pNode->fastSaxify(rContext); + } + rContext.mxDocHandler->endDocument(); + } + + void SAL_CALL CDocument::addListener(const Reference< XStreamListener >& aListener ) + throw (RuntimeException) + { + m_streamListeners.insert(aListener); + } + + void SAL_CALL CDocument::removeListener(const Reference< XStreamListener >& aListener ) + throw (RuntimeException) + { + m_streamListeners.erase(aListener); + } + + // IO context functions for libxml2 interaction + typedef struct { + Reference< XOutputStream > stream; + bool allowClose; + } IOContext; + + extern "C" { + // write callback + // int xmlOutputWriteCallback (void * context, const char * buffer, int len) + static int writeCallback(void *context, const char* buffer, int len){ + // create a sequence and write it to the stream + IOContext *pContext = static_cast<IOContext*>(context); + Sequence<sal_Int8> bs(reinterpret_cast<const sal_Int8*>(buffer), len); + pContext->stream->writeBytes(bs); + return len; + } + + // clsoe callback + //int xmlOutputCloseCallback (void * context) + static int closeCallback(void *context) + { + IOContext *pContext = static_cast<IOContext*>(context); + if (pContext->allowClose) { + pContext->stream->closeOutput(); + } + return 0; + } + } // extern "C" + + void SAL_CALL CDocument::start() + throw (RuntimeException) + { + if (! m_rOutputStream.is()) return; + + // notify listners about start + listenerlist_t::const_iterator iter1 = m_streamListeners.begin(); + while (iter1 != m_streamListeners.end()) { + Reference< XStreamListener > aListener = *iter1; + aListener->started(); + iter1++; + } + + // setup libxml IO and write data to output stream + IOContext ioctx = {m_rOutputStream, false}; + xmlOutputBufferPtr pOut = xmlOutputBufferCreateIO( + writeCallback, closeCallback, &ioctx, NULL); + xmlSaveFileTo(pOut, m_aNodePtr->doc, NULL); + + // call listeners + listenerlist_t::const_iterator iter2 = m_streamListeners.begin(); + while (iter2 != m_streamListeners.end()) { + Reference< XStreamListener > aListener = *iter2; + aListener->closed(); + iter2++; + } + + } + + void SAL_CALL CDocument::terminate() + throw (RuntimeException) + { + // not supported + } + + void SAL_CALL CDocument::setOutputStream( const Reference< XOutputStream >& aStream ) + throw (RuntimeException) + { + m_rOutputStream = aStream; + } + + Reference< XOutputStream > SAL_CALL CDocument::getOutputStream() throw (RuntimeException) + { + return m_rOutputStream; + } + + // Creates an Attr of the given name. + Reference< XAttr > SAL_CALL CDocument::createAttribute(const OUString& name) + throw (RuntimeException, DOMException) + { + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + return Reference< XAttr >(static_cast< CAttr* >( + CNode::get((xmlNodePtr)xmlNewDocProp(m_aDocPtr, xName, NULL)))); + }; + + // Creates an attribute of the given qualified name and namespace URI. + Reference< XAttr > SAL_CALL CDocument::createAttributeNS( + const OUString& ns, const OUString& qname) + throw (RuntimeException, DOMException) + { + + // libxml does not allow a NS definition to be attached to an + // attribute node - which is a good thing, since namespaces are + // only defined as parts of element nodes + // thus, we create a temporary element node which carries the ns definition + // and is removed/merged as soon as the attribute gets append to it's + // actual parent + sal_Int32 i = qname.indexOf(':'); + OString oPrefix, oName, oUri; + xmlChar *xPrefix, *xName, *xUri; + if (i != -1) + { + oPrefix = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8); + xPrefix = (xmlChar*)oPrefix.getStr(); + oName = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8); + } + else + { + xPrefix = (xmlChar*)""; + oName = OUStringToOString(qname, RTL_TEXTENCODING_UTF8); + } + xName = (xmlChar*)oName.getStr(); + oUri = OUStringToOString(ns, RTL_TEXTENCODING_UTF8); + xUri = (xmlChar*)oUri.getStr(); + + // create the carrier node + xmlNodePtr pNode = xmlNewDocNode(m_aDocPtr, NULL, (xmlChar*)"__private", NULL); + xmlNsPtr pNs = xmlNewNs(pNode, xUri, xPrefix); + xmlAttrPtr pAttr = xmlNewNsProp(pNode, pNs, xName, NULL); + return Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)pAttr))); + }; + + // Creates a CDATASection node whose value is the specified string. + Reference< XCDATASection > SAL_CALL CDocument::createCDATASection(const OUString& data) + throw (RuntimeException) + { + xmlChar *xData = (xmlChar*)OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr(); + xmlNodePtr pText = xmlNewCDataBlock(m_aDocPtr, xData, strlen((char*)xData)); + return Reference< XCDATASection >(static_cast< CCDATASection* >(CNode::get(pText))); + } + + // Creates a Comment node given the specified string. + Reference< XComment > SAL_CALL CDocument::createComment(const OUString& data) + throw (RuntimeException) + { + OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); + xmlChar *xData = (xmlChar*)o1.getStr(); + xmlNodePtr pComment = xmlNewDocComment(m_aDocPtr, xData); + return Reference< XComment >(static_cast< CComment* >(CNode::get(pComment))); + } + + //Creates an empty DocumentFragment object. + Reference< XDocumentFragment > SAL_CALL CDocument::createDocumentFragment() + throw (RuntimeException) + { + xmlNodePtr pFrag = xmlNewDocFragment(m_aDocPtr); + return Reference< XDocumentFragment >(static_cast< CDocumentFragment* >(CNode::get(pFrag))); + } + + // Creates an element of the type specified. + Reference< XElement > SAL_CALL CDocument::createElement(const OUString& tagName) + throw (RuntimeException, DOMException) + { + OString o1 = OUStringToOString(tagName, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + xmlNodePtr aNodePtr = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); + return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + } + + // Creates an element of the given qualified name and namespace URI. + Reference< XElement > SAL_CALL CDocument::createElementNS( + const OUString& ns, const OUString& qname) + throw (RuntimeException, DOMException) + { + sal_Int32 i = qname.indexOf(':'); + if (ns.getLength() == 0) throw RuntimeException(); + xmlChar *xPrefix; + xmlChar *xName; + OString o1, o2, o3; + if ( i != -1) { + o1 = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8); + xPrefix = (xmlChar*)o1.getStr(); + o2 = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8); + xName = (xmlChar*)o2.getStr(); + } else { + // default prefix + xPrefix = (xmlChar*)""; + o2 = OUStringToOString(qname, RTL_TEXTENCODING_UTF8); + xName = (xmlChar*)o2.getStr(); + } + o3 = OUStringToOString(ns, RTL_TEXTENCODING_UTF8); + xmlChar *xUri = (xmlChar*)o3.getStr(); + + // xmlNsPtr aNsPtr = xmlNewReconciledNs? + // xmlNsPtr aNsPtr = xmlNewGlobalNs? + xmlNodePtr aNodePtr = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); + xmlNsPtr pNs = xmlNewNs(aNodePtr, xUri, xPrefix); + xmlSetNs(aNodePtr, pNs); + return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + } + + //Creates an EntityReference object. + Reference< XEntityReference > SAL_CALL CDocument::createEntityReference(const OUString& name) + throw (RuntimeException, DOMException) + { + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)o1.getStr(); + xmlNodePtr aNodePtr = xmlNewReference(m_aDocPtr, xName); + return Reference< XEntityReference >(static_cast< CEntityReference* >(CNode::get(aNodePtr))); + } + + // Creates a ProcessingInstruction node given the specified name and + // data strings. + Reference< XProcessingInstruction > SAL_CALL CDocument::createProcessingInstruction( + const OUString& target, const OUString& data) + throw (RuntimeException, DOMException) + { + OString o1 = OUStringToOString(target, RTL_TEXTENCODING_UTF8); + xmlChar *xTarget = (xmlChar*)o1.getStr(); + OString o2 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); + xmlChar *xData = (xmlChar*)o2.getStr(); + xmlNodePtr aNodePtr = xmlNewPI(xTarget, xData); + aNodePtr->doc = m_aDocPtr; + return Reference< XProcessingInstruction >(static_cast< CProcessingInstruction* >(CNode::get(aNodePtr))); + } + + // Creates a Text node given the specified string. + Reference< XText > SAL_CALL CDocument::createTextNode(const OUString& data) + throw (RuntimeException) + { + OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); + xmlChar *xData = (xmlChar*)o1.getStr(); + xmlNodePtr aNodePtr = xmlNewDocText(m_aDocPtr, xData); + return Reference< XText >(static_cast< CText* >(CNode::get(aNodePtr))); + } + + // The Document Type Declaration (see DocumentType) associated with this + // document. + Reference< XDocumentType > SAL_CALL CDocument::getDoctype() + throw (RuntimeException) + { + // find the doc type + xmlNodePtr cur = m_aDocPtr->children; + while (cur != NULL) + { + if (cur->type == XML_DOCUMENT_TYPE_NODE || cur->type == XML_DTD_NODE) + break; + } + return Reference< XDocumentType >(static_cast< CDocumentType* >(CNode::get(cur))); + } + + /// get the pointer to the root element node of the document + static xmlNodePtr SAL_CALL _getDocumentRootPtr(xmlDocPtr i_pDocument) { + // find the document element + xmlNodePtr cur = i_pDocument->children; + while (cur != NULL) + { + if (cur->type == XML_ELEMENT_NODE) + break; + cur = cur->next; + } + return cur; + } + + // This is a convenience attribute that allows direct access to the child + // node that is the root element of the document. + Reference< XElement > SAL_CALL CDocument::getDocumentElement() + throw (RuntimeException) + { + xmlNodePtr cur = _getDocumentRootPtr(m_aDocPtr); + return Reference< XElement >(static_cast< CElement* >(CNode::get(cur))); + } + + static xmlNodePtr _search_element_by_id(const xmlNodePtr cur, const xmlChar* id) + { + + if (cur == NULL) + return NULL; + // look in current node + if (cur->type == XML_ELEMENT_NODE) + { + xmlAttrPtr a = cur->properties; + while (a != NULL) + { + if (a->atype == XML_ATTRIBUTE_ID) { + if (strcmp((char*)a->children->content, (char*)id) == 0) + return cur; + } + a = a->next; + } + } + // look in children + xmlNodePtr result = _search_element_by_id(cur->children, id); + if (result != NULL) + return result; + result = _search_element_by_id(cur->next, id); + return result; + } + + // Returns the Element whose ID is given by elementId. + Reference< XElement > SAL_CALL CDocument::getElementById(const OUString& elementId) + throw (RuntimeException) + { + // search the tree for an element with the given ID + OString o1 = OUStringToOString(elementId, RTL_TEXTENCODING_UTF8); + xmlChar *xId = (xmlChar*)o1.getStr(); + xmlNodePtr pStart = CNode::getNodePtr(getDocumentElement().get()); + xmlNodePtr aNodePtr = _search_element_by_id(pStart, xId); + return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + } + + + Reference< XNodeList > SAL_CALL CDocument::getElementsByTagName(const OUString& tagname) + throw (RuntimeException) + { + // build a list + return Reference< XNodeList >( + new CElementList(static_cast< CElement* >( + this->getDocumentElement().get()), tagname)); + } + + Reference< XNodeList > SAL_CALL CDocument::getElementsByTagNameNS( + const OUString& namespaceURI, const OUString& localName) + throw (RuntimeException) + { + return Reference< XNodeList >( + new CElementList(static_cast< CElement* >( + this->getDocumentElement().get()), namespaceURI, localName)); + } + + Reference< XDOMImplementation > SAL_CALL CDocument::getImplementation() + throw (RuntimeException) + { + // XXX + return Reference< XDOMImplementation >(CDOMImplementation::get()); + } + + // helper function to recall import for siblings + static Reference< XNode > _import_siblings ( + const Reference< XNode > aNode, const Reference< XNode> parent, CDocument* pTarget) + { + Reference< XNode > sibling = aNode; + Reference< XNode > tmp; + Reference< XNode > firstImported; + while (sibling.is()) + { + tmp = pTarget->importNode(sibling, sal_True); + parent->appendChild(tmp); + if (!firstImported.is()) + firstImported = tmp; + sibling = sibling->getNextSibling(); + } + return firstImported; + } + + Reference< XNode > SAL_CALL CDocument::importNode( + const Reference< XNode >& importedNode, sal_Bool deep) + throw (RuntimeException, DOMException) + { + // this node could be from another memory model + // only use uno interfaces to access is!!! + + // allready in doc? + if ( importedNode->getOwnerDocument() == + Reference< XDocument>(static_cast< CDocument* >(CNode::get((xmlNodePtr)m_aDocPtr)))) + return importedNode; + + Reference< XNode > aNode; + NodeType aNodeType = importedNode->getNodeType(); + switch (aNodeType) + { + case NodeType_ATTRIBUTE_NODE: + { + Reference< XAttr > attr(importedNode, UNO_QUERY); + Reference< XAttr > newAttr = createAttribute(attr->getName()); + newAttr->setValue(attr->getValue()); + aNode.set(newAttr, UNO_QUERY); + break; + } + case NodeType_CDATA_SECTION_NODE: + { + Reference< XCDATASection > cdata(importedNode, UNO_QUERY); + Reference< XCDATASection > newCdata = createCDATASection(cdata->getData()); + aNode.set(newCdata, UNO_QUERY); + break; + } + case NodeType_COMMENT_NODE: + { + Reference< XComment > comment(importedNode, UNO_QUERY); + Reference< XComment > newComment = createComment(comment->getData()); + aNode.set(newComment, UNO_QUERY); + break; + } + case NodeType_DOCUMENT_FRAGMENT_NODE: + { + Reference< XDocumentFragment > frag(importedNode, UNO_QUERY); + Reference< XDocumentFragment > newFrag = createDocumentFragment(); + aNode.set(newFrag, UNO_QUERY); + break; + } + case NodeType_ELEMENT_NODE: + { + Reference< XElement > element(importedNode, UNO_QUERY); + OUString aNsUri = importedNode->getNamespaceURI(); + OUString aNsPrefix = importedNode->getPrefix(); + OUString aQName = element->getTagName(); + Reference< XElement > newElement; + if (aNsUri.getLength() > 0) + { + + if (aNsPrefix.getLength() > 0) + aQName = aNsPrefix + OUString::createFromAscii(":") + aQName; + newElement = createElementNS(aNsUri, aQName); + } + else + newElement = createElement(aQName); + + // get attributes + if (element->hasAttributes()) + { + Reference< XNamedNodeMap > attribs = element->getAttributes(); + Reference< XAttr > curAttr; + for (sal_Int32 i = 0; i < attribs->getLength(); i++) + { + curAttr = Reference< XAttr >(attribs->item(i), UNO_QUERY); + OUString aAttrUri = curAttr->getNamespaceURI(); + OUString aAttrPrefix = curAttr->getPrefix(); + OUString aAttrName = curAttr->getName(); + if (aAttrUri.getLength() > 0) + { + if (aAttrPrefix.getLength() > 0) + aAttrName = aAttrPrefix + OUString::createFromAscii(":") + aAttrName; + newElement->setAttributeNS(aAttrUri, aAttrName, curAttr->getValue()); + } + else + newElement->setAttribute(aAttrName, curAttr->getValue()); + } + } + aNode.set(newElement, UNO_QUERY); + break; + } + case NodeType_ENTITY_REFERENCE_NODE: + { + Reference< XEntityReference > ref(importedNode, UNO_QUERY); + Reference< XEntityReference > newRef(createEntityReference(ref->getNodeName())); + aNode.set(newRef, UNO_QUERY); + break; + } + case NodeType_PROCESSING_INSTRUCTION_NODE: + { + Reference< XProcessingInstruction > pi(importedNode, UNO_QUERY); + Reference< XProcessingInstruction > newPi( + createProcessingInstruction(pi->getTarget(), pi->getData())); + aNode.set(newPi, UNO_QUERY); + break; + } + case NodeType_TEXT_NODE: + { + Reference< XText > text(importedNode, UNO_QUERY); + Reference< XText > newText(createTextNode(text->getData())); + aNode.set(newText, UNO_QUERY); + break; + } + case NodeType_ENTITY_NODE: + case NodeType_DOCUMENT_NODE: + case NodeType_DOCUMENT_TYPE_NODE: + case NodeType_NOTATION_NODE: + default: + // can't be imported + throw RuntimeException(); + + } + if (deep) + { + // get children and import them + Reference< XNode > child = importedNode->getFirstChild(); + if (child.is()) + { + _import_siblings(child, aNode, this); + } + } + + /* DOMNodeInsertedIntoDocument + * Fired when a node is being inserted into a document, + * either through direct insertion of the Node or insertion of a + * subtree in which it is contained. This event is dispatched after + * the insertion has taken place. The target of this event is the node + * being inserted. If the Node is being directly inserted the DOMNodeInserted + * event will fire before the DOMNodeInsertedIntoDocument event. + * Bubbles: No + * Cancelable: No + * Context Info: None + */ + if (aNode.is()) + { + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMNodeInsertedIntoDocument")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMNodeInsertedIntoDocument") + , sal_True, sal_False, Reference< XNode >(), + OUString(), OUString(), OUString(), (AttrChangeType)0 ); + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + } + + return aNode; + } + OUString SAL_CALL CDocument::getNodeName()throw (RuntimeException) + { + return OUString::createFromAscii("#document"); + } + OUString SAL_CALL CDocument::getNodeValue() throw (RuntimeException) + { + return OUString(); + } + + Reference< XEvent > SAL_CALL CDocument::createEvent(const OUString& aType) throw (RuntimeException) + { + events::CEvent *pEvent = 0; + if ( + aType.compareToAscii("DOMSubtreeModified") == 0|| + aType.compareToAscii("DOMNodeInserted") == 0|| + aType.compareToAscii("DOMNodeRemoved") == 0|| + aType.compareToAscii("DOMNodeRemovedFromDocument") == 0|| + aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0|| + aType.compareToAscii("DOMAttrModified") == 0|| + aType.compareToAscii("DOMCharacterDataModified") == 0) + { + pEvent = new events::CMutationEvent; + + } else if ( + aType.compareToAscii("DOMFocusIn") == 0|| + aType.compareToAscii("DOMFocusOut") == 0|| + aType.compareToAscii("DOMActivate") == 0) + { + pEvent = new events::CUIEvent; + } else if ( + aType.compareToAscii("click") == 0|| + aType.compareToAscii("mousedown") == 0|| + aType.compareToAscii("mouseup") == 0|| + aType.compareToAscii("mouseover") == 0|| + aType.compareToAscii("mousemove") == 0|| + aType.compareToAscii("mouseout") == 0 ) + { + pEvent = new events::CMouseEvent; + } + else // generic event + { + pEvent = new events::CEvent; + } + return Reference< XEvent >(pEvent); + } + + // ::com::sun::star::xml::sax::XSAXSerializable + void SAL_CALL CDocument::serialize( + const Reference< XDocumentHandler >& i_xHandler, + const Sequence< beans::StringPair >& i_rNamespaces) + throw (RuntimeException, SAXException) + { + // add new namespaces to root node + xmlNodePtr pRoot = _getDocumentRootPtr(m_aDocPtr); + if (0 != pRoot) { + const beans::StringPair * pSeq = i_rNamespaces.getConstArray(); + for (const beans::StringPair *pNsDef = pSeq; + pNsDef < pSeq + i_rNamespaces.getLength(); ++pNsDef) { + OString prefix = OUStringToOString(pNsDef->First, + RTL_TEXTENCODING_UTF8); + OString href = OUStringToOString(pNsDef->Second, + RTL_TEXTENCODING_UTF8); + // this will only add the ns if it does not exist already + xmlNewNs(pRoot, reinterpret_cast<const xmlChar*>(href.getStr()), + reinterpret_cast<const xmlChar*>(prefix.getStr())); + } + // eliminate duplicate namespace declarations + _nscleanup(pRoot->children, pRoot); + } + saxify(i_xHandler); + } + + // ::com::sun::star::xml::sax::XFastSAXSerializable + void SAL_CALL CDocument::fastSerialize( const Reference< XFastDocumentHandler >& i_xHandler, + const Reference< XFastTokenHandler >& i_xTokenHandler, + const Sequence< beans::StringPair >& i_rNamespaces, + const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& i_rRegisterNamespaces ) + throw (SAXException, RuntimeException) + { + // add new namespaces to root node + xmlNodePtr pRoot = _getDocumentRootPtr(m_aDocPtr); + if (0 != pRoot) { + const beans::StringPair * pSeq = i_rNamespaces.getConstArray(); + for (const beans::StringPair *pNsDef = pSeq; + pNsDef < pSeq + i_rNamespaces.getLength(); ++pNsDef) { + OString prefix = OUStringToOString(pNsDef->First, + RTL_TEXTENCODING_UTF8); + OString href = OUStringToOString(pNsDef->Second, + RTL_TEXTENCODING_UTF8); + // this will only add the ns if it does not exist already + xmlNewNs(pRoot, reinterpret_cast<const xmlChar*>(href.getStr()), + reinterpret_cast<const xmlChar*>(prefix.getStr())); + } + // eliminate duplicate namespace declarations + _nscleanup(pRoot->children, pRoot); + } + + Context aContext(i_xHandler, + i_xTokenHandler); + + // register namespace ids + const beans::Pair<OUString,sal_Int32>* pSeq = i_rRegisterNamespaces.getConstArray(); + for (const beans::Pair<OUString,sal_Int32>* pNs = pSeq; + pNs < pSeq + i_rRegisterNamespaces.getLength(); ++pNs) + { + OSL_ENSURE(pNs->Second >= FastToken::NAMESPACE, + "CDocument::fastSerialize(): invalid NS token id"); + aContext.maNamespaceMap[ pNs->First ] = pNs->Second; + } + + fastSaxify(aContext); + } +} |