xref: /AOO41X/main/unoxml/source/dom/document.cxx (revision e9cbe144f2ea8c6fdc1a6527ef692f8296608908)
1*e9cbe144SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*e9cbe144SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*e9cbe144SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*e9cbe144SAndrew Rist  * distributed with this work for additional information
6*e9cbe144SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*e9cbe144SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*e9cbe144SAndrew Rist  * "License"); you may not use this file except in compliance
9*e9cbe144SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*e9cbe144SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*e9cbe144SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*e9cbe144SAndrew Rist  * software distributed under the License is distributed on an
15*e9cbe144SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*e9cbe144SAndrew Rist  * KIND, either express or implied.  See the License for the
17*e9cbe144SAndrew Rist  * specific language governing permissions and limitations
18*e9cbe144SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*e9cbe144SAndrew Rist  *************************************************************/
21*e9cbe144SAndrew Rist 
22*e9cbe144SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include <com/sun/star/uno/Sequence.h>
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include "document.hxx"
27cdf0e10cSrcweir #include "attr.hxx"
28cdf0e10cSrcweir #include "element.hxx"
29cdf0e10cSrcweir #include "cdatasection.hxx"
30cdf0e10cSrcweir #include "documentfragment.hxx"
31cdf0e10cSrcweir #include "text.hxx"
32cdf0e10cSrcweir #include "cdatasection.hxx"
33cdf0e10cSrcweir #include "comment.hxx"
34cdf0e10cSrcweir #include "processinginstruction.hxx"
35cdf0e10cSrcweir #include "entityreference.hxx"
36cdf0e10cSrcweir #include "documenttype.hxx"
37cdf0e10cSrcweir #include "elementlist.hxx"
38cdf0e10cSrcweir #include "domimplementation.hxx"
39cdf0e10cSrcweir #include <entity.hxx>
40cdf0e10cSrcweir #include <notation.hxx>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #include "../events/event.hxx"
43cdf0e10cSrcweir #include "../events/mutationevent.hxx"
44cdf0e10cSrcweir #include "../events/uievent.hxx"
45cdf0e10cSrcweir #include "../events/mouseevent.hxx"
46cdf0e10cSrcweir #include "../events/eventdispatcher.hxx"
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include <string.h>
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #include <com/sun/star/xml/sax/FastToken.hpp>
51cdf0e10cSrcweir #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
52cdf0e10cSrcweir 
53cdf0e10cSrcweir namespace DOM
54cdf0e10cSrcweir {
lcl_getDocumentType(xmlDocPtr const i_pDocument)55cdf0e10cSrcweir     static xmlNodePtr lcl_getDocumentType(xmlDocPtr const i_pDocument)
56cdf0e10cSrcweir     {
57cdf0e10cSrcweir         // find the doc type
58cdf0e10cSrcweir         xmlNodePtr cur = i_pDocument->children;
59cdf0e10cSrcweir         while (cur != NULL)
60cdf0e10cSrcweir         {
61cdf0e10cSrcweir             if ((cur->type == XML_DOCUMENT_TYPE_NODE) ||
62cdf0e10cSrcweir                 (cur->type == XML_DTD_NODE)) {
63cdf0e10cSrcweir                     return cur;
64cdf0e10cSrcweir             }
65cdf0e10cSrcweir         }
66cdf0e10cSrcweir         return 0;
67cdf0e10cSrcweir     }
68cdf0e10cSrcweir 
69cdf0e10cSrcweir     /// get the pointer to the root element node of the document
lcl_getDocumentRootPtr(xmlDocPtr const i_pDocument)70cdf0e10cSrcweir     static xmlNodePtr lcl_getDocumentRootPtr(xmlDocPtr const i_pDocument)
71cdf0e10cSrcweir     {
72cdf0e10cSrcweir         // find the document element
73cdf0e10cSrcweir         xmlNodePtr cur = i_pDocument->children;
74cdf0e10cSrcweir         while (cur != NULL)
75cdf0e10cSrcweir         {
76cdf0e10cSrcweir             if (cur->type == XML_ELEMENT_NODE)
77cdf0e10cSrcweir                 break;
78cdf0e10cSrcweir             cur = cur->next;
79cdf0e10cSrcweir         }
80cdf0e10cSrcweir         return cur;
81cdf0e10cSrcweir     }
82cdf0e10cSrcweir 
CDocument(xmlDocPtr const pDoc)83cdf0e10cSrcweir     CDocument::CDocument(xmlDocPtr const pDoc)
84cdf0e10cSrcweir         : CDocument_Base(*this, m_Mutex,
85cdf0e10cSrcweir                 NodeType_DOCUMENT_NODE, reinterpret_cast<xmlNodePtr>(pDoc))
86cdf0e10cSrcweir         , m_aDocPtr(pDoc)
87cdf0e10cSrcweir         , m_streamListeners()
88cdf0e10cSrcweir         , m_pEventDispatcher(new events::CEventDispatcher())
89cdf0e10cSrcweir     {
90cdf0e10cSrcweir     }
91cdf0e10cSrcweir 
CreateCDocument(xmlDocPtr const pDoc)92cdf0e10cSrcweir     ::rtl::Reference<CDocument> CDocument::CreateCDocument(xmlDocPtr const pDoc)
93cdf0e10cSrcweir     {
94cdf0e10cSrcweir         ::rtl::Reference<CDocument> const xDoc(new CDocument(pDoc));
95cdf0e10cSrcweir         // add the doc itself to its nodemap!
96cdf0e10cSrcweir         xDoc->m_NodeMap.insert(
97cdf0e10cSrcweir             nodemap_t::value_type(reinterpret_cast<xmlNodePtr>(pDoc),
98cdf0e10cSrcweir                 ::std::make_pair(
99cdf0e10cSrcweir                     WeakReference<XNode>(static_cast<XDocument*>(xDoc.get())),
100cdf0e10cSrcweir                     xDoc.get())));
101cdf0e10cSrcweir         return xDoc;
102cdf0e10cSrcweir     }
103cdf0e10cSrcweir 
~CDocument()104cdf0e10cSrcweir     CDocument::~CDocument()
105cdf0e10cSrcweir     {
106cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
107cdf0e10cSrcweir #ifdef DBG_UTIL
108cdf0e10cSrcweir         // node map must be empty now, otherwise CDocument must not die!
109cdf0e10cSrcweir         for (nodemap_t::iterator i = m_NodeMap.begin();
110cdf0e10cSrcweir                 i != m_NodeMap.end(); ++i)
111cdf0e10cSrcweir         {
112cdf0e10cSrcweir             Reference<XNode> const xNode(i->second.first);
113cdf0e10cSrcweir             OSL_ENSURE(!xNode.is(),
114cdf0e10cSrcweir             "CDocument::~CDocument(): ERROR: live node in document node map!");
115cdf0e10cSrcweir         }
116cdf0e10cSrcweir #endif
117cdf0e10cSrcweir         xmlFreeDoc(m_aDocPtr);
118cdf0e10cSrcweir     }
119cdf0e10cSrcweir 
120cdf0e10cSrcweir 
GetEventDispatcher()121cdf0e10cSrcweir     events::CEventDispatcher & CDocument::GetEventDispatcher()
122cdf0e10cSrcweir     {
123cdf0e10cSrcweir         return *m_pEventDispatcher;
124cdf0e10cSrcweir     }
125cdf0e10cSrcweir 
GetDocumentElement()126cdf0e10cSrcweir     ::rtl::Reference< CElement > CDocument::GetDocumentElement()
127cdf0e10cSrcweir     {
128cdf0e10cSrcweir         xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr);
129cdf0e10cSrcweir         ::rtl::Reference< CElement > const xRet(
130cdf0e10cSrcweir             dynamic_cast<CElement*>(GetCNode(pNode).get()));
131cdf0e10cSrcweir         return xRet;
132cdf0e10cSrcweir     }
133cdf0e10cSrcweir 
134cdf0e10cSrcweir     void
RemoveCNode(xmlNodePtr const pNode,CNode const * const pCNode)135cdf0e10cSrcweir     CDocument::RemoveCNode(xmlNodePtr const pNode, CNode const*const pCNode)
136cdf0e10cSrcweir     {
137cdf0e10cSrcweir         nodemap_t::iterator const i = m_NodeMap.find(pNode);
138cdf0e10cSrcweir         if (i != m_NodeMap.end()) {
139cdf0e10cSrcweir             // #i113681# consider this scenario:
140cdf0e10cSrcweir             // T1 calls ~CNode
141cdf0e10cSrcweir             // T2 calls getCNode:    lookup will find i->second->first invalid
142cdf0e10cSrcweir             //                       so a new CNode is created and inserted
143cdf0e10cSrcweir             // T1 calls removeCNode: i->second->second now points to a
144cdf0e10cSrcweir             //                       different CNode instance!
145cdf0e10cSrcweir             //
146cdf0e10cSrcweir             // check that the CNode is the right one
147cdf0e10cSrcweir             CNode *const pCurrent = i->second.second;
148cdf0e10cSrcweir             if (pCurrent == pCNode) {
149cdf0e10cSrcweir                 m_NodeMap.erase(i);
150cdf0e10cSrcweir             }
151cdf0e10cSrcweir         }
152cdf0e10cSrcweir     }
153cdf0e10cSrcweir 
154cdf0e10cSrcweir     /** NB: this is the CNode factory.
155cdf0e10cSrcweir         it is the only place where CNodes may be instantiated.
156cdf0e10cSrcweir         all CNodes must be registered at the m_NodeMap.
157cdf0e10cSrcweir      */
158cdf0e10cSrcweir     ::rtl::Reference<CNode>
GetCNode(xmlNodePtr const pNode,bool const bCreate)159cdf0e10cSrcweir     CDocument::GetCNode(xmlNodePtr const pNode, bool const bCreate)
160cdf0e10cSrcweir     {
161cdf0e10cSrcweir         if (0 == pNode) {
162cdf0e10cSrcweir             return 0;
163cdf0e10cSrcweir         }
164cdf0e10cSrcweir         //check whether there is already an instance for this node
165cdf0e10cSrcweir         nodemap_t::const_iterator const i = m_NodeMap.find(pNode);
166cdf0e10cSrcweir         if (i != m_NodeMap.end()) {
167cdf0e10cSrcweir             // #i113681# check that the CNode is still alive
168cdf0e10cSrcweir             uno::Reference<XNode> const xNode(i->second.first);
169cdf0e10cSrcweir             if (xNode.is())
170cdf0e10cSrcweir             {
171cdf0e10cSrcweir                 ::rtl::Reference<CNode> ret(i->second.second);
172cdf0e10cSrcweir                 OSL_ASSERT(ret.is());
173cdf0e10cSrcweir                 return ret;
174cdf0e10cSrcweir             }
175cdf0e10cSrcweir         }
176cdf0e10cSrcweir 
177cdf0e10cSrcweir         if (!bCreate) { return 0; }
178cdf0e10cSrcweir 
179cdf0e10cSrcweir         // there is not yet an instance wrapping this node,
180cdf0e10cSrcweir         // create it and store it in the map
181cdf0e10cSrcweir 
182cdf0e10cSrcweir         ::rtl::Reference<CNode> pCNode;
183cdf0e10cSrcweir         switch (pNode->type)
184cdf0e10cSrcweir         {
185cdf0e10cSrcweir             case XML_ELEMENT_NODE:
186cdf0e10cSrcweir                 // m_aNodeType = NodeType::ELEMENT_NODE;
187cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(
188cdf0e10cSrcweir                         new CElement(*this, m_Mutex, pNode));
189cdf0e10cSrcweir             break;
190cdf0e10cSrcweir             case XML_TEXT_NODE:
191cdf0e10cSrcweir                 // m_aNodeType = NodeType::TEXT_NODE;
192cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(
193cdf0e10cSrcweir                         new CText(*this, m_Mutex, pNode));
194cdf0e10cSrcweir             break;
195cdf0e10cSrcweir             case XML_CDATA_SECTION_NODE:
196cdf0e10cSrcweir                 // m_aNodeType = NodeType::CDATA_SECTION_NODE;
197cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(
198cdf0e10cSrcweir                         new CCDATASection(*this, m_Mutex, pNode));
199cdf0e10cSrcweir             break;
200cdf0e10cSrcweir             case XML_ENTITY_REF_NODE:
201cdf0e10cSrcweir                 // m_aNodeType = NodeType::ENTITY_REFERENCE_NODE;
202cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(
203cdf0e10cSrcweir                         new CEntityReference(*this, m_Mutex, pNode));
204cdf0e10cSrcweir             break;
205cdf0e10cSrcweir             case XML_ENTITY_NODE:
206cdf0e10cSrcweir                 // m_aNodeType = NodeType::ENTITY_NODE;
207cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(new CEntity(*this, m_Mutex,
208cdf0e10cSrcweir                             reinterpret_cast<xmlEntityPtr>(pNode)));
209cdf0e10cSrcweir             break;
210cdf0e10cSrcweir             case XML_PI_NODE:
211cdf0e10cSrcweir                 // m_aNodeType = NodeType::PROCESSING_INSTRUCTION_NODE;
212cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(
213cdf0e10cSrcweir                         new CProcessingInstruction(*this, m_Mutex, pNode));
214cdf0e10cSrcweir             break;
215cdf0e10cSrcweir             case XML_COMMENT_NODE:
216cdf0e10cSrcweir                 // m_aNodeType = NodeType::COMMENT_NODE;
217cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(
218cdf0e10cSrcweir                         new CComment(*this, m_Mutex, pNode));
219cdf0e10cSrcweir             break;
220cdf0e10cSrcweir             case XML_DOCUMENT_NODE:
221cdf0e10cSrcweir                 // m_aNodeType = NodeType::DOCUMENT_NODE;
222cdf0e10cSrcweir                 OSL_ENSURE(false, "CDocument::GetCNode is not supposed to"
223cdf0e10cSrcweir                         " create a CDocument!!!");
224cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(new CDocument(
225cdf0e10cSrcweir                             reinterpret_cast<xmlDocPtr>(pNode)));
226cdf0e10cSrcweir             break;
227cdf0e10cSrcweir             case XML_DOCUMENT_TYPE_NODE:
228cdf0e10cSrcweir             case XML_DTD_NODE:
229cdf0e10cSrcweir                 // m_aNodeType = NodeType::DOCUMENT_TYPE_NODE;
230cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(new CDocumentType(*this, m_Mutex,
231cdf0e10cSrcweir                             reinterpret_cast<xmlDtdPtr>(pNode)));
232cdf0e10cSrcweir             break;
233cdf0e10cSrcweir             case XML_DOCUMENT_FRAG_NODE:
234cdf0e10cSrcweir                 // m_aNodeType = NodeType::DOCUMENT_FRAGMENT_NODE;
235cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(
236cdf0e10cSrcweir                         new CDocumentFragment(*this, m_Mutex, pNode));
237cdf0e10cSrcweir             break;
238cdf0e10cSrcweir             case XML_NOTATION_NODE:
239cdf0e10cSrcweir                 // m_aNodeType = NodeType::NOTATION_NODE;
240cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(new CNotation(*this, m_Mutex,
241cdf0e10cSrcweir                             reinterpret_cast<xmlNotationPtr>(pNode)));
242cdf0e10cSrcweir             break;
243cdf0e10cSrcweir             case XML_ATTRIBUTE_NODE:
244cdf0e10cSrcweir                 // m_aNodeType = NodeType::ATTRIBUTE_NODE;
245cdf0e10cSrcweir                 pCNode = static_cast< CNode* >(new CAttr(*this, m_Mutex,
246cdf0e10cSrcweir                             reinterpret_cast<xmlAttrPtr>(pNode)));
247cdf0e10cSrcweir             break;
248cdf0e10cSrcweir             // unsupported node types
249cdf0e10cSrcweir             case XML_HTML_DOCUMENT_NODE:
250cdf0e10cSrcweir             case XML_ELEMENT_DECL:
251cdf0e10cSrcweir             case XML_ATTRIBUTE_DECL:
252cdf0e10cSrcweir             case XML_ENTITY_DECL:
253cdf0e10cSrcweir             case XML_NAMESPACE_DECL:
254cdf0e10cSrcweir             default:
255cdf0e10cSrcweir             break;
256cdf0e10cSrcweir         }
257cdf0e10cSrcweir 
258cdf0e10cSrcweir         if (pCNode != 0) {
259cdf0e10cSrcweir             bool const bInserted = m_NodeMap.insert(
260cdf0e10cSrcweir                     nodemap_t::value_type(pNode,
261cdf0e10cSrcweir                         ::std::make_pair(WeakReference<XNode>(pCNode.get()),
262cdf0e10cSrcweir                         pCNode.get()))
263cdf0e10cSrcweir                 ).second;
264cdf0e10cSrcweir             OSL_ASSERT(bInserted);
265cdf0e10cSrcweir             if (!bInserted) {
266cdf0e10cSrcweir                 // if insertion failed, delete new instance and return null
267cdf0e10cSrcweir                 return 0;
268cdf0e10cSrcweir             }
269cdf0e10cSrcweir         }
270cdf0e10cSrcweir 
271cdf0e10cSrcweir         OSL_ENSURE(pCNode.is(), "no node produced during CDocument::GetCNode!");
272cdf0e10cSrcweir         return pCNode;
273cdf0e10cSrcweir     }
274cdf0e10cSrcweir 
275cdf0e10cSrcweir 
GetOwnerDocument()276cdf0e10cSrcweir     CDocument & CDocument::GetOwnerDocument()
277cdf0e10cSrcweir     {
278cdf0e10cSrcweir         return *this;
279cdf0e10cSrcweir     }
280cdf0e10cSrcweir 
saxify(const Reference<XDocumentHandler> & i_xHandler)281cdf0e10cSrcweir     void CDocument::saxify(const Reference< XDocumentHandler >& i_xHandler)
282cdf0e10cSrcweir     {
283cdf0e10cSrcweir         i_xHandler->startDocument();
284cdf0e10cSrcweir         for (xmlNodePtr pChild = m_aNodePtr->children;
285cdf0e10cSrcweir                         pChild != 0; pChild = pChild->next) {
286cdf0e10cSrcweir             ::rtl::Reference<CNode> const pNode = GetCNode(pChild);
287cdf0e10cSrcweir             OSL_ENSURE(pNode != 0, "CNode::get returned 0");
288cdf0e10cSrcweir             pNode->saxify(i_xHandler);
289cdf0e10cSrcweir         }
290cdf0e10cSrcweir         i_xHandler->endDocument();
291cdf0e10cSrcweir     }
292cdf0e10cSrcweir 
fastSaxify(Context & rContext)293cdf0e10cSrcweir     void CDocument::fastSaxify( Context& rContext )
294cdf0e10cSrcweir     {
295cdf0e10cSrcweir         rContext.mxDocHandler->startDocument();
296cdf0e10cSrcweir         for (xmlNodePtr pChild = m_aNodePtr->children;
297cdf0e10cSrcweir                         pChild != 0; pChild = pChild->next) {
298cdf0e10cSrcweir             ::rtl::Reference<CNode> const pNode = GetCNode(pChild);
299cdf0e10cSrcweir             OSL_ENSURE(pNode != 0, "CNode::get returned 0");
300cdf0e10cSrcweir             pNode->fastSaxify(rContext);
301cdf0e10cSrcweir         }
302cdf0e10cSrcweir         rContext.mxDocHandler->endDocument();
303cdf0e10cSrcweir     }
304cdf0e10cSrcweir 
IsChildTypeAllowed(NodeType const nodeType)305cdf0e10cSrcweir     bool CDocument::IsChildTypeAllowed(NodeType const nodeType)
306cdf0e10cSrcweir     {
307cdf0e10cSrcweir         switch (nodeType) {
308cdf0e10cSrcweir             case NodeType_PROCESSING_INSTRUCTION_NODE:
309cdf0e10cSrcweir             case NodeType_COMMENT_NODE:
310cdf0e10cSrcweir                 return true;
311cdf0e10cSrcweir             case NodeType_ELEMENT_NODE:
312cdf0e10cSrcweir                  // there may be only one!
313cdf0e10cSrcweir                 return 0 == lcl_getDocumentRootPtr(m_aDocPtr);
314cdf0e10cSrcweir             case NodeType_DOCUMENT_TYPE_NODE:
315cdf0e10cSrcweir                  // there may be only one!
316cdf0e10cSrcweir                 return 0 == lcl_getDocumentType(m_aDocPtr);
317cdf0e10cSrcweir             default:
318cdf0e10cSrcweir                 return false;
319cdf0e10cSrcweir         }
320cdf0e10cSrcweir     }
321cdf0e10cSrcweir 
322cdf0e10cSrcweir 
addListener(const Reference<XStreamListener> & aListener)323cdf0e10cSrcweir 	void SAL_CALL CDocument::addListener(const Reference< XStreamListener >& aListener )
324cdf0e10cSrcweir 		throw (RuntimeException)
325cdf0e10cSrcweir     {
326cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
327cdf0e10cSrcweir 
328cdf0e10cSrcweir 		m_streamListeners.insert(aListener);
329cdf0e10cSrcweir 	}
330cdf0e10cSrcweir 
removeListener(const Reference<XStreamListener> & aListener)331cdf0e10cSrcweir 	void SAL_CALL CDocument::removeListener(const Reference< XStreamListener >& aListener )
332cdf0e10cSrcweir 		throw (RuntimeException)
333cdf0e10cSrcweir     {
334cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 		m_streamListeners.erase(aListener);
337cdf0e10cSrcweir 	}
338cdf0e10cSrcweir 
339cdf0e10cSrcweir 	// IO context functions for libxml2 interaction
340cdf0e10cSrcweir 	typedef struct {
341cdf0e10cSrcweir 		Reference< XOutputStream > stream;
342cdf0e10cSrcweir 		bool allowClose;
343cdf0e10cSrcweir 	} IOContext;
344cdf0e10cSrcweir 
345cdf0e10cSrcweir     extern "C" {
346cdf0e10cSrcweir 	// write callback
347cdf0e10cSrcweir 	// int xmlOutputWriteCallback (void * context, const char * buffer, int len)
writeCallback(void * context,const char * buffer,int len)348cdf0e10cSrcweir     static int writeCallback(void *context, const char* buffer, int len){
349cdf0e10cSrcweir 		// create a sequence and write it to the stream
350cdf0e10cSrcweir 		IOContext *pContext = static_cast<IOContext*>(context);
351cdf0e10cSrcweir 		Sequence<sal_Int8> bs(reinterpret_cast<const sal_Int8*>(buffer), len);
352cdf0e10cSrcweir 		pContext->stream->writeBytes(bs);
353cdf0e10cSrcweir 		return len;
354cdf0e10cSrcweir 	}
355cdf0e10cSrcweir 
356cdf0e10cSrcweir 	// clsoe callback
357cdf0e10cSrcweir 	//int xmlOutputCloseCallback (void * context)
closeCallback(void * context)358cdf0e10cSrcweir 	static int closeCallback(void *context)
359cdf0e10cSrcweir 	{
360cdf0e10cSrcweir 		IOContext *pContext = static_cast<IOContext*>(context);
361cdf0e10cSrcweir 		if (pContext->allowClose) {
362cdf0e10cSrcweir 			pContext->stream->closeOutput();
363cdf0e10cSrcweir 		}
364cdf0e10cSrcweir 		return 0;
365cdf0e10cSrcweir 	}
366cdf0e10cSrcweir     } // extern "C"
367cdf0e10cSrcweir 
start()368cdf0e10cSrcweir 	void SAL_CALL CDocument::start()
369cdf0e10cSrcweir 		throw (RuntimeException)
370cdf0e10cSrcweir 	{
371cdf0e10cSrcweir         listenerlist_t streamListeners;
372cdf0e10cSrcweir         {
373cdf0e10cSrcweir             ::osl::MutexGuard const g(m_Mutex);
374cdf0e10cSrcweir 
375cdf0e10cSrcweir             if (! m_rOutputStream.is()) { throw RuntimeException(); }
376cdf0e10cSrcweir             streamListeners = m_streamListeners;
377cdf0e10cSrcweir         }
378cdf0e10cSrcweir 
379cdf0e10cSrcweir 		// notify listeners about start
380cdf0e10cSrcweir 		listenerlist_t::const_iterator iter1 = streamListeners.begin();
381cdf0e10cSrcweir         while (iter1 != streamListeners.end()) {
382cdf0e10cSrcweir 			Reference< XStreamListener > aListener = *iter1;
383cdf0e10cSrcweir 			aListener->started();
384cdf0e10cSrcweir 			iter1++;
385cdf0e10cSrcweir 		}
386cdf0e10cSrcweir 
387cdf0e10cSrcweir         {
388cdf0e10cSrcweir             ::osl::MutexGuard const g(m_Mutex);
389cdf0e10cSrcweir 
390cdf0e10cSrcweir             // check again! could have been reset...
391cdf0e10cSrcweir             if (! m_rOutputStream.is()) { throw RuntimeException(); }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir             // setup libxml IO and write data to output stream
394cdf0e10cSrcweir             IOContext ioctx = {m_rOutputStream, false};
395cdf0e10cSrcweir             xmlOutputBufferPtr pOut = xmlOutputBufferCreateIO(
396cdf0e10cSrcweir                 writeCallback, closeCallback, &ioctx, NULL);
397cdf0e10cSrcweir             xmlSaveFileTo(pOut, m_aNodePtr->doc, NULL);
398cdf0e10cSrcweir         }
399cdf0e10cSrcweir 
400cdf0e10cSrcweir 		// call listeners
401cdf0e10cSrcweir         listenerlist_t::const_iterator iter2 = streamListeners.begin();
402cdf0e10cSrcweir         while (iter2 != streamListeners.end()) {
403cdf0e10cSrcweir 			Reference< XStreamListener > aListener = *iter2;
404cdf0e10cSrcweir 			aListener->closed();
405cdf0e10cSrcweir 			iter2++;
406cdf0e10cSrcweir 		}
407cdf0e10cSrcweir 	}
408cdf0e10cSrcweir 
terminate()409cdf0e10cSrcweir 	void SAL_CALL CDocument::terminate()
410cdf0e10cSrcweir 		throw (RuntimeException)
411cdf0e10cSrcweir 	{
412cdf0e10cSrcweir 		// not supported
413cdf0e10cSrcweir 	}
414cdf0e10cSrcweir 
setOutputStream(const Reference<XOutputStream> & aStream)415cdf0e10cSrcweir 	void SAL_CALL CDocument::setOutputStream( const Reference< XOutputStream >& aStream )
416cdf0e10cSrcweir 		throw (RuntimeException)
417cdf0e10cSrcweir 	{
418cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
419cdf0e10cSrcweir 
420cdf0e10cSrcweir 		m_rOutputStream = aStream;
421cdf0e10cSrcweir 	}
422cdf0e10cSrcweir 
getOutputStream()423cdf0e10cSrcweir 	Reference< XOutputStream > SAL_CALL  CDocument::getOutputStream() throw (RuntimeException)
424cdf0e10cSrcweir 	{
425cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
426cdf0e10cSrcweir 
427cdf0e10cSrcweir 		return m_rOutputStream;
428cdf0e10cSrcweir 	}
429cdf0e10cSrcweir 
430cdf0e10cSrcweir     // Creates an Attr of the given name.
createAttribute(const OUString & name)431cdf0e10cSrcweir     Reference< XAttr > SAL_CALL CDocument::createAttribute(const OUString& name)
432cdf0e10cSrcweir         throw (RuntimeException, DOMException)
433cdf0e10cSrcweir     {
434cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
437cdf0e10cSrcweir         xmlChar *xName = (xmlChar*)o1.getStr();
438cdf0e10cSrcweir         xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr, xName, NULL);
439cdf0e10cSrcweir         ::rtl::Reference< CAttr > const pCAttr(
440cdf0e10cSrcweir             dynamic_cast< CAttr* >(GetCNode(
441cdf0e10cSrcweir                     reinterpret_cast<xmlNodePtr>(pAttr)).get()));
442cdf0e10cSrcweir         pCAttr->m_bUnlinked = true;
443cdf0e10cSrcweir         return pCAttr.get();
444cdf0e10cSrcweir     };
445cdf0e10cSrcweir 
446cdf0e10cSrcweir     // Creates an attribute of the given qualified name and namespace URI.
createAttributeNS(const OUString & ns,const OUString & qname)447cdf0e10cSrcweir     Reference< XAttr > SAL_CALL CDocument::createAttributeNS(
448cdf0e10cSrcweir             const OUString& ns, const OUString& qname)
449cdf0e10cSrcweir         throw (RuntimeException, DOMException)
450cdf0e10cSrcweir     {
451cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
452cdf0e10cSrcweir 
453cdf0e10cSrcweir         // libxml does not allow a NS definition to be attached to an
454cdf0e10cSrcweir         // attribute node - which is a good thing, since namespaces are
455cdf0e10cSrcweir         // only defined as parts of element nodes
456cdf0e10cSrcweir         // thus the namespace data is stored in CAttr::m_pNamespace
457cdf0e10cSrcweir         sal_Int32 i = qname.indexOf(':');
458cdf0e10cSrcweir         OString oPrefix, oName, oUri;
459cdf0e10cSrcweir         if (i != -1)
460cdf0e10cSrcweir         {
461cdf0e10cSrcweir             oPrefix = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8);
462cdf0e10cSrcweir             oName = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8);
463cdf0e10cSrcweir         }
464cdf0e10cSrcweir         else
465cdf0e10cSrcweir         {
466cdf0e10cSrcweir             oName = OUStringToOString(qname, RTL_TEXTENCODING_UTF8);
467cdf0e10cSrcweir         }
468cdf0e10cSrcweir         oUri = OUStringToOString(ns, RTL_TEXTENCODING_UTF8);
469cdf0e10cSrcweir         xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr,
470cdf0e10cSrcweir                 reinterpret_cast<xmlChar const*>(oName.getStr()), 0);
471cdf0e10cSrcweir         ::rtl::Reference< CAttr > const pCAttr(
472cdf0e10cSrcweir             dynamic_cast< CAttr* >(GetCNode(
473cdf0e10cSrcweir                     reinterpret_cast<xmlNodePtr>(pAttr)).get()));
474cdf0e10cSrcweir         if (!pCAttr.is()) { throw RuntimeException(); }
475cdf0e10cSrcweir         // store the namespace data!
476cdf0e10cSrcweir         pCAttr->m_pNamespace.reset( new stringpair_t(oUri, oPrefix) );
477cdf0e10cSrcweir         pCAttr->m_bUnlinked = true;
478cdf0e10cSrcweir 
479cdf0e10cSrcweir         return pCAttr.get();
480cdf0e10cSrcweir     };
481cdf0e10cSrcweir 
482cdf0e10cSrcweir     // Creates a CDATASection node whose value is the specified string.
createCDATASection(const OUString & data)483cdf0e10cSrcweir     Reference< XCDATASection > SAL_CALL CDocument::createCDATASection(const OUString& data)
484cdf0e10cSrcweir         throw (RuntimeException)
485cdf0e10cSrcweir     {
486cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
487cdf0e10cSrcweir 
488cdf0e10cSrcweir         OString const oData(
489cdf0e10cSrcweir                 ::rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8));
490cdf0e10cSrcweir         xmlChar const*const pData =
491cdf0e10cSrcweir             reinterpret_cast<xmlChar const*>(oData.getStr());
492cdf0e10cSrcweir         xmlNodePtr const pText =
493cdf0e10cSrcweir             xmlNewCDataBlock(m_aDocPtr, pData, strlen(oData.getStr()));
494cdf0e10cSrcweir         Reference< XCDATASection > const xRet(
495cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pText).get()),
496cdf0e10cSrcweir             UNO_QUERY_THROW);
497cdf0e10cSrcweir         return xRet;
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir 
500cdf0e10cSrcweir     // Creates a Comment node given the specified string.
createComment(const OUString & data)501cdf0e10cSrcweir     Reference< XComment > SAL_CALL CDocument::createComment(const OUString& data)
502cdf0e10cSrcweir         throw (RuntimeException)
503cdf0e10cSrcweir     {
504cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
505cdf0e10cSrcweir 
506cdf0e10cSrcweir         OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8);
507cdf0e10cSrcweir         xmlChar *xData = (xmlChar*)o1.getStr();
508cdf0e10cSrcweir         xmlNodePtr pComment = xmlNewDocComment(m_aDocPtr, xData);
509cdf0e10cSrcweir         Reference< XComment > const xRet(
510cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pComment).get()),
511cdf0e10cSrcweir             UNO_QUERY_THROW);
512cdf0e10cSrcweir         return xRet;
513cdf0e10cSrcweir     }
514cdf0e10cSrcweir 
515cdf0e10cSrcweir     //Creates an empty DocumentFragment object.
createDocumentFragment()516cdf0e10cSrcweir     Reference< XDocumentFragment > SAL_CALL CDocument::createDocumentFragment()
517cdf0e10cSrcweir         throw (RuntimeException)
518cdf0e10cSrcweir     {
519cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
520cdf0e10cSrcweir 
521cdf0e10cSrcweir         xmlNodePtr pFrag = xmlNewDocFragment(m_aDocPtr);
522cdf0e10cSrcweir         Reference< XDocumentFragment > const xRet(
523cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pFrag).get()),
524cdf0e10cSrcweir             UNO_QUERY_THROW);
525cdf0e10cSrcweir         return xRet;
526cdf0e10cSrcweir     }
527cdf0e10cSrcweir 
528cdf0e10cSrcweir     // Creates an element of the type specified.
createElement(const OUString & tagName)529cdf0e10cSrcweir     Reference< XElement > SAL_CALL CDocument::createElement(const OUString& tagName)
530cdf0e10cSrcweir         throw (RuntimeException, DOMException)
531cdf0e10cSrcweir     {
532cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
533cdf0e10cSrcweir 
534cdf0e10cSrcweir         OString o1 = OUStringToOString(tagName, RTL_TEXTENCODING_UTF8);
535cdf0e10cSrcweir         xmlChar *xName = (xmlChar*)o1.getStr();
536cdf0e10cSrcweir         xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL);
537cdf0e10cSrcweir         Reference< XElement > const xRet(
538cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pNode).get()),
539cdf0e10cSrcweir             UNO_QUERY_THROW);
540cdf0e10cSrcweir         return xRet;
541cdf0e10cSrcweir     }
542cdf0e10cSrcweir 
543cdf0e10cSrcweir     // Creates an element of the given qualified name and namespace URI.
createElementNS(const OUString & ns,const OUString & qname)544cdf0e10cSrcweir     Reference< XElement > SAL_CALL CDocument::createElementNS(
545cdf0e10cSrcweir             const OUString& ns, const OUString& qname)
546cdf0e10cSrcweir         throw (RuntimeException, DOMException)
547cdf0e10cSrcweir     {
548cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
549cdf0e10cSrcweir 
550cdf0e10cSrcweir         sal_Int32 i = qname.indexOf(':');
551cdf0e10cSrcweir         if (ns.getLength() == 0) throw RuntimeException();
552cdf0e10cSrcweir         xmlChar *xPrefix;
553cdf0e10cSrcweir         xmlChar *xName;
554cdf0e10cSrcweir         OString o1, o2, o3;
555cdf0e10cSrcweir         if ( i != -1) {
556cdf0e10cSrcweir             o1 = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8);
557cdf0e10cSrcweir             xPrefix = (xmlChar*)o1.getStr();
558cdf0e10cSrcweir             o2 = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8);
559cdf0e10cSrcweir             xName = (xmlChar*)o2.getStr();
560cdf0e10cSrcweir         } else {
561cdf0e10cSrcweir             // default prefix
562cdf0e10cSrcweir             xPrefix = (xmlChar*)"";
563cdf0e10cSrcweir             o2 = OUStringToOString(qname, RTL_TEXTENCODING_UTF8);
564cdf0e10cSrcweir             xName = (xmlChar*)o2.getStr();
565cdf0e10cSrcweir         }
566cdf0e10cSrcweir         o3 = OUStringToOString(ns, RTL_TEXTENCODING_UTF8);
567cdf0e10cSrcweir         xmlChar *xUri = (xmlChar*)o3.getStr();
568cdf0e10cSrcweir 
569cdf0e10cSrcweir         // xmlNsPtr aNsPtr = xmlNewReconciledNs?
570cdf0e10cSrcweir         // xmlNsPtr aNsPtr = xmlNewGlobalNs?
571cdf0e10cSrcweir         xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL);
572cdf0e10cSrcweir         xmlNsPtr const pNs = xmlNewNs(pNode, xUri, xPrefix);
573cdf0e10cSrcweir         xmlSetNs(pNode, pNs);
574cdf0e10cSrcweir         Reference< XElement > const xRet(
575cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pNode).get()),
576cdf0e10cSrcweir             UNO_QUERY_THROW);
577cdf0e10cSrcweir         return xRet;
578cdf0e10cSrcweir     }
579cdf0e10cSrcweir 
580cdf0e10cSrcweir     //Creates an EntityReference object.
createEntityReference(const OUString & name)581cdf0e10cSrcweir     Reference< XEntityReference > SAL_CALL CDocument::createEntityReference(const OUString& name)
582cdf0e10cSrcweir         throw (RuntimeException, DOMException)
583cdf0e10cSrcweir     {
584cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
585cdf0e10cSrcweir 
586cdf0e10cSrcweir         OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
587cdf0e10cSrcweir         xmlChar *xName = (xmlChar*)o1.getStr();
588cdf0e10cSrcweir         xmlNodePtr const pNode = xmlNewReference(m_aDocPtr, xName);
589cdf0e10cSrcweir         Reference< XEntityReference > const xRet(
590cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pNode).get()),
591cdf0e10cSrcweir             UNO_QUERY_THROW);
592cdf0e10cSrcweir         return xRet;
593cdf0e10cSrcweir     }
594cdf0e10cSrcweir 
595cdf0e10cSrcweir     // Creates a ProcessingInstruction node given the specified name and
596cdf0e10cSrcweir     // data strings.
createProcessingInstruction(const OUString & target,const OUString & data)597cdf0e10cSrcweir     Reference< XProcessingInstruction > SAL_CALL CDocument::createProcessingInstruction(
598cdf0e10cSrcweir             const OUString& target, const OUString& data)
599cdf0e10cSrcweir         throw (RuntimeException, DOMException)
600cdf0e10cSrcweir     {
601cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
602cdf0e10cSrcweir 
603cdf0e10cSrcweir         OString o1 = OUStringToOString(target, RTL_TEXTENCODING_UTF8);
604cdf0e10cSrcweir         xmlChar *xTarget = (xmlChar*)o1.getStr();
605cdf0e10cSrcweir         OString o2 = OUStringToOString(data, RTL_TEXTENCODING_UTF8);
606cdf0e10cSrcweir         xmlChar *xData = (xmlChar*)o2.getStr();
607cdf0e10cSrcweir         xmlNodePtr const pNode = xmlNewDocPI(m_aDocPtr, xTarget, xData);
608cdf0e10cSrcweir         pNode->doc = m_aDocPtr;
609cdf0e10cSrcweir         Reference< XProcessingInstruction > const xRet(
610cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pNode).get()),
611cdf0e10cSrcweir             UNO_QUERY_THROW);
612cdf0e10cSrcweir         return xRet;
613cdf0e10cSrcweir     }
614cdf0e10cSrcweir 
615cdf0e10cSrcweir     // Creates a Text node given the specified string.
createTextNode(const OUString & data)616cdf0e10cSrcweir     Reference< XText > SAL_CALL CDocument::createTextNode(const OUString& data)
617cdf0e10cSrcweir         throw (RuntimeException)
618cdf0e10cSrcweir     {
619cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
620cdf0e10cSrcweir 
621cdf0e10cSrcweir         OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8);
622cdf0e10cSrcweir         xmlChar *xData = (xmlChar*)o1.getStr();
623cdf0e10cSrcweir         xmlNodePtr const pNode = xmlNewDocText(m_aDocPtr, xData);
624cdf0e10cSrcweir         Reference< XText > const xRet(
625cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pNode).get()),
626cdf0e10cSrcweir             UNO_QUERY_THROW);
627cdf0e10cSrcweir         return xRet;
628cdf0e10cSrcweir     }
629cdf0e10cSrcweir 
630cdf0e10cSrcweir     // The Document Type Declaration (see DocumentType) associated with this
631cdf0e10cSrcweir     // document.
getDoctype()632cdf0e10cSrcweir     Reference< XDocumentType > SAL_CALL CDocument::getDoctype()
633cdf0e10cSrcweir         throw (RuntimeException)
634cdf0e10cSrcweir     {
635cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
636cdf0e10cSrcweir 
637cdf0e10cSrcweir         xmlNodePtr const pDocType(lcl_getDocumentType(m_aDocPtr));
638cdf0e10cSrcweir         Reference< XDocumentType > const xRet(
639cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pDocType).get()),
640cdf0e10cSrcweir             UNO_QUERY);
641cdf0e10cSrcweir         return xRet;
642cdf0e10cSrcweir     }
643cdf0e10cSrcweir 
644cdf0e10cSrcweir     // This is a convenience attribute that allows direct access to the child
645cdf0e10cSrcweir     // node that is the root element of the document.
getDocumentElement()646cdf0e10cSrcweir     Reference< XElement > SAL_CALL CDocument::getDocumentElement()
647cdf0e10cSrcweir         throw (RuntimeException)
648cdf0e10cSrcweir     {
649cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
650cdf0e10cSrcweir 
651cdf0e10cSrcweir         xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr);
652cdf0e10cSrcweir         if (!pNode) { return 0; }
653cdf0e10cSrcweir         Reference< XElement > const xRet(
654cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pNode).get()),
655cdf0e10cSrcweir             UNO_QUERY);
656cdf0e10cSrcweir         return xRet;
657cdf0e10cSrcweir     }
658cdf0e10cSrcweir 
659cdf0e10cSrcweir     static xmlNodePtr
lcl_search_element_by_id(const xmlNodePtr cur,const xmlChar * id)660cdf0e10cSrcweir     lcl_search_element_by_id(const xmlNodePtr cur, const xmlChar* id)
661cdf0e10cSrcweir     {
662cdf0e10cSrcweir         if (cur == NULL)
663cdf0e10cSrcweir             return NULL;
664cdf0e10cSrcweir         // look in current node
665cdf0e10cSrcweir         if (cur->type == XML_ELEMENT_NODE)
666cdf0e10cSrcweir         {
667cdf0e10cSrcweir             xmlAttrPtr a = cur->properties;
668cdf0e10cSrcweir             while (a != NULL)
669cdf0e10cSrcweir             {
670cdf0e10cSrcweir                 if (a->atype == XML_ATTRIBUTE_ID) {
671cdf0e10cSrcweir                     if (strcmp((char*)a->children->content, (char*)id) == 0)
672cdf0e10cSrcweir                         return cur;
673cdf0e10cSrcweir                 }
674cdf0e10cSrcweir                 a = a->next;
675cdf0e10cSrcweir             }
676cdf0e10cSrcweir         }
677cdf0e10cSrcweir         // look in children
678cdf0e10cSrcweir         xmlNodePtr result = lcl_search_element_by_id(cur->children, id);
679cdf0e10cSrcweir         if (result != NULL)
680cdf0e10cSrcweir             return result;
681cdf0e10cSrcweir         result = lcl_search_element_by_id(cur->next, id);
682cdf0e10cSrcweir             return result;
683cdf0e10cSrcweir     }
684cdf0e10cSrcweir 
685cdf0e10cSrcweir     // Returns the Element whose ID is given by elementId.
686cdf0e10cSrcweir     Reference< XElement > SAL_CALL
getElementById(const OUString & elementId)687cdf0e10cSrcweir     CDocument::getElementById(const OUString& elementId)
688cdf0e10cSrcweir         throw (RuntimeException)
689cdf0e10cSrcweir     {
690cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
691cdf0e10cSrcweir 
692cdf0e10cSrcweir         // search the tree for an element with the given ID
693cdf0e10cSrcweir         OString o1 = OUStringToOString(elementId, RTL_TEXTENCODING_UTF8);
694cdf0e10cSrcweir         xmlChar *xId = (xmlChar*)o1.getStr();
695cdf0e10cSrcweir         xmlNodePtr const pStart = lcl_getDocumentRootPtr(m_aDocPtr);
696cdf0e10cSrcweir         if (!pStart) { return 0; }
697cdf0e10cSrcweir         xmlNodePtr const pNode = lcl_search_element_by_id(pStart, xId);
698cdf0e10cSrcweir         Reference< XElement > const xRet(
699cdf0e10cSrcweir             static_cast< XNode* >(GetCNode(pNode).get()),
700cdf0e10cSrcweir             UNO_QUERY);
701cdf0e10cSrcweir         return xRet;
702cdf0e10cSrcweir     }
703cdf0e10cSrcweir 
704cdf0e10cSrcweir 
705cdf0e10cSrcweir     Reference< XNodeList > SAL_CALL
getElementsByTagName(OUString const & rTagname)706cdf0e10cSrcweir     CDocument::getElementsByTagName(OUString const& rTagname)
707cdf0e10cSrcweir             throw (RuntimeException)
708cdf0e10cSrcweir     {
709cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
710cdf0e10cSrcweir 
711cdf0e10cSrcweir         Reference< XNodeList > const xRet(
712cdf0e10cSrcweir             new CElementList(this->GetDocumentElement(), m_Mutex, rTagname));
713cdf0e10cSrcweir         return xRet;
714cdf0e10cSrcweir     }
715cdf0e10cSrcweir 
getElementsByTagNameNS(OUString const & rNamespaceURI,OUString const & rLocalName)716cdf0e10cSrcweir     Reference< XNodeList > SAL_CALL CDocument::getElementsByTagNameNS(
717cdf0e10cSrcweir             OUString const& rNamespaceURI, OUString const& rLocalName)
718cdf0e10cSrcweir         throw (RuntimeException)
719cdf0e10cSrcweir     {
720cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
721cdf0e10cSrcweir 
722cdf0e10cSrcweir         Reference< XNodeList > const xRet(
723cdf0e10cSrcweir             new CElementList(this->GetDocumentElement(), m_Mutex,
724cdf0e10cSrcweir                 rLocalName, &rNamespaceURI));
725cdf0e10cSrcweir         return xRet;
726cdf0e10cSrcweir     }
727cdf0e10cSrcweir 
getImplementation()728cdf0e10cSrcweir     Reference< XDOMImplementation > SAL_CALL CDocument::getImplementation()
729cdf0e10cSrcweir         throw (RuntimeException)
730cdf0e10cSrcweir     {
731cdf0e10cSrcweir         // does not need mutex currently
732cdf0e10cSrcweir         return Reference< XDOMImplementation >(CDOMImplementation::get());
733cdf0e10cSrcweir     }
734cdf0e10cSrcweir 
735cdf0e10cSrcweir     // helper function to recursively import siblings
lcl_ImportSiblings(Reference<XDocument> const & xTargetDocument,Reference<XNode> const & xTargetParent,Reference<XNode> const & xChild)736cdf0e10cSrcweir     static void lcl_ImportSiblings(
737cdf0e10cSrcweir         Reference< XDocument > const& xTargetDocument,
738cdf0e10cSrcweir         Reference< XNode > const& xTargetParent,
739cdf0e10cSrcweir         Reference< XNode > const& xChild)
740cdf0e10cSrcweir     {
741cdf0e10cSrcweir         Reference< XNode > xSibling = xChild;
742cdf0e10cSrcweir         while (xSibling.is())
743cdf0e10cSrcweir         {
744cdf0e10cSrcweir             Reference< XNode > const xTmp(
745cdf0e10cSrcweir                     xTargetDocument->importNode(xSibling, sal_True));
746cdf0e10cSrcweir             xTargetParent->appendChild(xTmp);
747cdf0e10cSrcweir             xSibling = xSibling->getNextSibling();
748cdf0e10cSrcweir         }
749cdf0e10cSrcweir     }
750cdf0e10cSrcweir 
751cdf0e10cSrcweir     static Reference< XNode >
lcl_ImportNode(Reference<XDocument> const & xDocument,Reference<XNode> const & xImportedNode,sal_Bool deep)752cdf0e10cSrcweir     lcl_ImportNode( Reference< XDocument > const& xDocument,
753cdf0e10cSrcweir             Reference< XNode > const& xImportedNode, sal_Bool deep)
754cdf0e10cSrcweir     {
755cdf0e10cSrcweir         Reference< XNode > xNode;
756cdf0e10cSrcweir         NodeType aNodeType = xImportedNode->getNodeType();
757cdf0e10cSrcweir         switch (aNodeType)
758cdf0e10cSrcweir         {
759cdf0e10cSrcweir         case NodeType_ATTRIBUTE_NODE:
760cdf0e10cSrcweir         {
761cdf0e10cSrcweir             Reference< XAttr > const xAttr(xImportedNode, UNO_QUERY_THROW);
762cdf0e10cSrcweir             Reference< XAttr > const xNew =
763cdf0e10cSrcweir                 xDocument->createAttribute(xAttr->getName());
764cdf0e10cSrcweir             xNew->setValue(xAttr->getValue());
765cdf0e10cSrcweir             xNode.set(xNew, UNO_QUERY);
766cdf0e10cSrcweir             break;
767cdf0e10cSrcweir         }
768cdf0e10cSrcweir         case NodeType_CDATA_SECTION_NODE:
769cdf0e10cSrcweir         {
770cdf0e10cSrcweir             Reference< XCDATASection > const xCData(xImportedNode,
771cdf0e10cSrcweir                     UNO_QUERY_THROW);
772cdf0e10cSrcweir             Reference< XCDATASection > const xNewCData =
773cdf0e10cSrcweir                 xDocument->createCDATASection(xCData->getData());
774cdf0e10cSrcweir             xNode.set(xNewCData, UNO_QUERY);
775cdf0e10cSrcweir             break;
776cdf0e10cSrcweir         }
777cdf0e10cSrcweir         case NodeType_COMMENT_NODE:
778cdf0e10cSrcweir         {
779cdf0e10cSrcweir             Reference< XComment > const xComment(xImportedNode,
780cdf0e10cSrcweir                     UNO_QUERY_THROW);
781cdf0e10cSrcweir             Reference< XComment > const xNewComment =
782cdf0e10cSrcweir                 xDocument->createComment(xComment->getData());
783cdf0e10cSrcweir             xNode.set(xNewComment, UNO_QUERY);
784cdf0e10cSrcweir             break;
785cdf0e10cSrcweir         }
786cdf0e10cSrcweir         case NodeType_DOCUMENT_FRAGMENT_NODE:
787cdf0e10cSrcweir         {
788cdf0e10cSrcweir             Reference< XDocumentFragment > const xFrag(xImportedNode,
789cdf0e10cSrcweir                     UNO_QUERY_THROW);
790cdf0e10cSrcweir             Reference< XDocumentFragment > const xNewFrag =
791cdf0e10cSrcweir                 xDocument->createDocumentFragment();
792cdf0e10cSrcweir             xNode.set(xNewFrag, UNO_QUERY);
793cdf0e10cSrcweir             break;
794cdf0e10cSrcweir         }
795cdf0e10cSrcweir         case NodeType_ELEMENT_NODE:
796cdf0e10cSrcweir         {
797cdf0e10cSrcweir             Reference< XElement > const xElement(xImportedNode,
798cdf0e10cSrcweir                     UNO_QUERY_THROW);
799cdf0e10cSrcweir             OUString const aNsUri = xImportedNode->getNamespaceURI();
800cdf0e10cSrcweir             OUString const aNsPrefix = xImportedNode->getPrefix();
801cdf0e10cSrcweir             OUString aQName = xElement->getTagName();
802cdf0e10cSrcweir             Reference< XElement > xNewElement;
803cdf0e10cSrcweir             if (aNsUri.getLength() > 0)
804cdf0e10cSrcweir             {
805cdf0e10cSrcweir                 if (aNsPrefix.getLength() > 0) {
806cdf0e10cSrcweir                     aQName = aNsPrefix + OUString::createFromAscii(":")
807cdf0e10cSrcweir                                 + aQName;
808cdf0e10cSrcweir                 }
809cdf0e10cSrcweir                 xNewElement = xDocument->createElementNS(aNsUri, aQName);
810cdf0e10cSrcweir             } else {
811cdf0e10cSrcweir                 xNewElement = xDocument->createElement(aQName);
812cdf0e10cSrcweir             }
813cdf0e10cSrcweir 
814cdf0e10cSrcweir             // get attributes
815cdf0e10cSrcweir             if (xElement->hasAttributes())
816cdf0e10cSrcweir             {
817cdf0e10cSrcweir                 Reference< XNamedNodeMap > attribs = xElement->getAttributes();
818cdf0e10cSrcweir                 for (sal_Int32 i = 0; i < attribs->getLength(); i++)
819cdf0e10cSrcweir                 {
820cdf0e10cSrcweir                     Reference< XAttr > const curAttr(attribs->item(i),
821cdf0e10cSrcweir                             UNO_QUERY_THROW);
822cdf0e10cSrcweir                     OUString const aAttrUri = curAttr->getNamespaceURI();
823cdf0e10cSrcweir                     OUString const aAttrPrefix = curAttr->getPrefix();
824cdf0e10cSrcweir                     OUString aAttrName = curAttr->getName();
825cdf0e10cSrcweir                     OUString const sValue = curAttr->getValue();
826cdf0e10cSrcweir                     if (aAttrUri.getLength() > 0)
827cdf0e10cSrcweir                     {
828cdf0e10cSrcweir                         if (aAttrPrefix.getLength() > 0) {
829cdf0e10cSrcweir                             aAttrName = aAttrPrefix +
830cdf0e10cSrcweir                                 OUString::createFromAscii(":") + aAttrName;
831cdf0e10cSrcweir                         }
832cdf0e10cSrcweir                         xNewElement->setAttributeNS(
833cdf0e10cSrcweir                                 aAttrUri, aAttrName, sValue);
834cdf0e10cSrcweir                     } else {
835cdf0e10cSrcweir                         xNewElement->setAttribute(aAttrName, sValue);
836cdf0e10cSrcweir                     }
837cdf0e10cSrcweir                 }
838cdf0e10cSrcweir             }
839cdf0e10cSrcweir             xNode.set(xNewElement, UNO_QUERY);
840cdf0e10cSrcweir             break;
841cdf0e10cSrcweir         }
842cdf0e10cSrcweir         case NodeType_ENTITY_REFERENCE_NODE:
843cdf0e10cSrcweir         {
844cdf0e10cSrcweir             Reference< XEntityReference > const xRef(xImportedNode,
845cdf0e10cSrcweir                     UNO_QUERY_THROW);
846cdf0e10cSrcweir             Reference< XEntityReference > const xNewRef(
847cdf0e10cSrcweir                 xDocument->createEntityReference(xRef->getNodeName()));
848cdf0e10cSrcweir             xNode.set(xNewRef, UNO_QUERY);
849cdf0e10cSrcweir             break;
850cdf0e10cSrcweir         }
851cdf0e10cSrcweir         case NodeType_PROCESSING_INSTRUCTION_NODE:
852cdf0e10cSrcweir         {
853cdf0e10cSrcweir             Reference< XProcessingInstruction > const xPi(xImportedNode,
854cdf0e10cSrcweir                     UNO_QUERY_THROW);
855cdf0e10cSrcweir             Reference< XProcessingInstruction > const xNewPi(
856cdf0e10cSrcweir                 xDocument->createProcessingInstruction(
857cdf0e10cSrcweir                     xPi->getTarget(), xPi->getData()));
858cdf0e10cSrcweir             xNode.set(xNewPi, UNO_QUERY);
859cdf0e10cSrcweir             break;
860cdf0e10cSrcweir         }
861cdf0e10cSrcweir         case NodeType_TEXT_NODE:
862cdf0e10cSrcweir         {
863cdf0e10cSrcweir             Reference< XText > const xText(xImportedNode, UNO_QUERY_THROW);
864cdf0e10cSrcweir             Reference< XText > const xNewText(
865cdf0e10cSrcweir                 xDocument->createTextNode(xText->getData()));
866cdf0e10cSrcweir             xNode.set(xNewText, UNO_QUERY);
867cdf0e10cSrcweir             break;
868cdf0e10cSrcweir         }
869cdf0e10cSrcweir         case NodeType_ENTITY_NODE:
870cdf0e10cSrcweir         case NodeType_DOCUMENT_NODE:
871cdf0e10cSrcweir         case NodeType_DOCUMENT_TYPE_NODE:
872cdf0e10cSrcweir         case NodeType_NOTATION_NODE:
873cdf0e10cSrcweir         default:
874cdf0e10cSrcweir             // can't be imported
875cdf0e10cSrcweir             throw RuntimeException();
876cdf0e10cSrcweir 
877cdf0e10cSrcweir         }
878cdf0e10cSrcweir         if (deep)
879cdf0e10cSrcweir         {
880cdf0e10cSrcweir             // get children and import them
881cdf0e10cSrcweir             Reference< XNode > const xChild = xImportedNode->getFirstChild();
882cdf0e10cSrcweir             if (xChild.is())
883cdf0e10cSrcweir             {
884cdf0e10cSrcweir                 lcl_ImportSiblings(xDocument, xNode, xChild);
885cdf0e10cSrcweir             }
886cdf0e10cSrcweir         }
887cdf0e10cSrcweir 
888cdf0e10cSrcweir         /* DOMNodeInsertedIntoDocument
889cdf0e10cSrcweir          * Fired when a node is being inserted into a document,
890cdf0e10cSrcweir          * either through direct insertion of the Node or insertion of a
891cdf0e10cSrcweir          * subtree in which it is contained. This event is dispatched after
892cdf0e10cSrcweir          * the insertion has taken place. The target of this event is the node
893cdf0e10cSrcweir          * being inserted. If the Node is being directly inserted the DOMNodeInserted
894cdf0e10cSrcweir          * event will fire before the DOMNodeInsertedIntoDocument event.
895cdf0e10cSrcweir          *   Bubbles: No
896cdf0e10cSrcweir          *   Cancelable: No
897cdf0e10cSrcweir          *   Context Info: None
898cdf0e10cSrcweir          */
899cdf0e10cSrcweir         if (xNode.is())
900cdf0e10cSrcweir         {
901cdf0e10cSrcweir             Reference< XDocumentEvent > const xDocevent(xDocument, UNO_QUERY);
902cdf0e10cSrcweir             Reference< XMutationEvent > const event(xDocevent->createEvent(
903cdf0e10cSrcweir                 OUString::createFromAscii("DOMNodeInsertedIntoDocument")),
904cdf0e10cSrcweir                 UNO_QUERY_THROW);
905cdf0e10cSrcweir             event->initMutationEvent(
906cdf0e10cSrcweir                 OUString::createFromAscii("DOMNodeInsertedIntoDocument")
907cdf0e10cSrcweir                 , sal_True, sal_False, Reference< XNode >(),
908cdf0e10cSrcweir                 OUString(), OUString(), OUString(), (AttrChangeType)0 );
909cdf0e10cSrcweir             Reference< XEventTarget > const xDocET(xDocument, UNO_QUERY);
910cdf0e10cSrcweir             xDocET->dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
911cdf0e10cSrcweir         }
912cdf0e10cSrcweir 
913cdf0e10cSrcweir         return xNode;
914cdf0e10cSrcweir     }
915cdf0e10cSrcweir 
importNode(Reference<XNode> const & xImportedNode,sal_Bool deep)916cdf0e10cSrcweir     Reference< XNode > SAL_CALL CDocument::importNode(
917cdf0e10cSrcweir             Reference< XNode > const& xImportedNode, sal_Bool deep)
918cdf0e10cSrcweir         throw (RuntimeException, DOMException)
919cdf0e10cSrcweir     {
920cdf0e10cSrcweir         if (!xImportedNode.is()) { throw RuntimeException(); }
921cdf0e10cSrcweir 
922cdf0e10cSrcweir         // NB: this whole operation inherently accesses 2 distinct documents.
923cdf0e10cSrcweir         // The imported node could even be from a different DOM implementation,
924cdf0e10cSrcweir         // so this implementation cannot make any assumptions about the
925cdf0e10cSrcweir         // locking strategy of the imported node.
926cdf0e10cSrcweir         // So the import takes no lock on this document;
927cdf0e10cSrcweir         // it only calls UNO methods on this document that temporarily
928cdf0e10cSrcweir         // lock the document, and UNO methods on the imported node that
929cdf0e10cSrcweir         // may temporarily lock the other document.
930cdf0e10cSrcweir         // As a consequence, the import is not atomic with regard to
931cdf0e10cSrcweir         // concurrent modifications of either document, but it should not
932cdf0e10cSrcweir         // deadlock.
933cdf0e10cSrcweir         // To ensure that no members are accessed, the implementation is in
934cdf0e10cSrcweir         // static non-member functions.
935cdf0e10cSrcweir 
936cdf0e10cSrcweir         Reference< XDocument > const xDocument(this);
937cdf0e10cSrcweir         // already in doc?
938cdf0e10cSrcweir         if (xImportedNode->getOwnerDocument() == xDocument) {
939cdf0e10cSrcweir             return xImportedNode;
940cdf0e10cSrcweir         }
941cdf0e10cSrcweir 
942cdf0e10cSrcweir         Reference< XNode > const xNode(
943cdf0e10cSrcweir             lcl_ImportNode(xDocument, xImportedNode, deep) );
944cdf0e10cSrcweir         return xNode;
945cdf0e10cSrcweir     }
946cdf0e10cSrcweir 
947cdf0e10cSrcweir 
getNodeName()948cdf0e10cSrcweir     OUString SAL_CALL CDocument::getNodeName()throw (RuntimeException)
949cdf0e10cSrcweir     {
950cdf0e10cSrcweir         // does not need mutex currently
951cdf0e10cSrcweir         return OUString::createFromAscii("#document");
952cdf0e10cSrcweir     }
953cdf0e10cSrcweir 
getNodeValue()954cdf0e10cSrcweir     OUString SAL_CALL CDocument::getNodeValue() throw (RuntimeException)
955cdf0e10cSrcweir     {
956cdf0e10cSrcweir         // does not need mutex currently
957cdf0e10cSrcweir         return OUString();
958cdf0e10cSrcweir     }
959cdf0e10cSrcweir 
cloneNode(sal_Bool bDeep)960cdf0e10cSrcweir     Reference< XNode > SAL_CALL CDocument::cloneNode(sal_Bool bDeep)
961cdf0e10cSrcweir         throw (RuntimeException)
962cdf0e10cSrcweir     {
963cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
964cdf0e10cSrcweir 
965cdf0e10cSrcweir         OSL_ASSERT(0 != m_aNodePtr);
966cdf0e10cSrcweir         if (0 == m_aNodePtr) {
967cdf0e10cSrcweir             return 0;
968cdf0e10cSrcweir         }
969cdf0e10cSrcweir         xmlDocPtr const pClone(xmlCopyDoc(m_aDocPtr, (bDeep) ? 1 : 0));
970cdf0e10cSrcweir         if (0 == pClone) { return 0; }
971cdf0e10cSrcweir         Reference< XNode > const xRet(
972cdf0e10cSrcweir             static_cast<CNode*>(CDocument::CreateCDocument(pClone).get()));
973cdf0e10cSrcweir         return xRet;
974cdf0e10cSrcweir     }
975cdf0e10cSrcweir 
createEvent(const OUString & aType)976cdf0e10cSrcweir     Reference< XEvent > SAL_CALL CDocument::createEvent(const OUString& aType) throw (RuntimeException)
977cdf0e10cSrcweir     {
978cdf0e10cSrcweir         // does not need mutex currently
979cdf0e10cSrcweir         events::CEvent *pEvent = 0;
980cdf0e10cSrcweir         if (
981cdf0e10cSrcweir             aType.compareToAscii("DOMSubtreeModified")          == 0||
982cdf0e10cSrcweir             aType.compareToAscii("DOMNodeInserted")             == 0||
983cdf0e10cSrcweir             aType.compareToAscii("DOMNodeRemoved")              == 0||
984cdf0e10cSrcweir             aType.compareToAscii("DOMNodeRemovedFromDocument")  == 0||
985cdf0e10cSrcweir             aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0||
986cdf0e10cSrcweir             aType.compareToAscii("DOMAttrModified")             == 0||
987cdf0e10cSrcweir             aType.compareToAscii("DOMCharacterDataModified")    == 0)
988cdf0e10cSrcweir         {
989cdf0e10cSrcweir             pEvent = new events::CMutationEvent;
990cdf0e10cSrcweir 
991cdf0e10cSrcweir         } else if (
992cdf0e10cSrcweir             aType.compareToAscii("DOMFocusIn")  == 0||
993cdf0e10cSrcweir             aType.compareToAscii("DOMFocusOut") == 0||
994cdf0e10cSrcweir             aType.compareToAscii("DOMActivate") == 0)
995cdf0e10cSrcweir         {
996cdf0e10cSrcweir             pEvent = new events::CUIEvent;
997cdf0e10cSrcweir         } else if (
998cdf0e10cSrcweir             aType.compareToAscii("click")     == 0||
999cdf0e10cSrcweir             aType.compareToAscii("mousedown") == 0||
1000cdf0e10cSrcweir             aType.compareToAscii("mouseup")   == 0||
1001cdf0e10cSrcweir             aType.compareToAscii("mouseover") == 0||
1002cdf0e10cSrcweir             aType.compareToAscii("mousemove") == 0||
1003cdf0e10cSrcweir             aType.compareToAscii("mouseout")  == 0 )
1004cdf0e10cSrcweir         {
1005cdf0e10cSrcweir             pEvent = new events::CMouseEvent;
1006cdf0e10cSrcweir         }
1007cdf0e10cSrcweir         else // generic event
1008cdf0e10cSrcweir         {
1009cdf0e10cSrcweir             pEvent = new events::CEvent;
1010cdf0e10cSrcweir         }
1011cdf0e10cSrcweir         return Reference< XEvent >(pEvent);
1012cdf0e10cSrcweir     }
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir     // ::com::sun::star::xml::sax::XSAXSerializable
serialize(const Reference<XDocumentHandler> & i_xHandler,const Sequence<beans::StringPair> & i_rNamespaces)1015cdf0e10cSrcweir     void SAL_CALL CDocument::serialize(
1016cdf0e10cSrcweir             const Reference< XDocumentHandler >& i_xHandler,
1017cdf0e10cSrcweir             const Sequence< beans::StringPair >& i_rNamespaces)
1018cdf0e10cSrcweir         throw (RuntimeException, SAXException)
1019cdf0e10cSrcweir     {
1020cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir         // add new namespaces to root node
1023cdf0e10cSrcweir         xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr);
1024cdf0e10cSrcweir         if (0 != pRoot) {
1025cdf0e10cSrcweir             const beans::StringPair * pSeq = i_rNamespaces.getConstArray();
1026cdf0e10cSrcweir             for (const beans::StringPair *pNsDef = pSeq;
1027cdf0e10cSrcweir                  pNsDef < pSeq + i_rNamespaces.getLength(); ++pNsDef) {
1028cdf0e10cSrcweir                 OString prefix = OUStringToOString(pNsDef->First,
1029cdf0e10cSrcweir                                     RTL_TEXTENCODING_UTF8);
1030cdf0e10cSrcweir                 OString href   = OUStringToOString(pNsDef->Second,
1031cdf0e10cSrcweir                                     RTL_TEXTENCODING_UTF8);
1032cdf0e10cSrcweir                 // this will only add the ns if it does not exist already
1033cdf0e10cSrcweir                 xmlNewNs(pRoot, reinterpret_cast<const xmlChar*>(href.getStr()),
1034cdf0e10cSrcweir                          reinterpret_cast<const xmlChar*>(prefix.getStr()));
1035cdf0e10cSrcweir             }
1036cdf0e10cSrcweir             // eliminate duplicate namespace declarations
1037cdf0e10cSrcweir             nscleanup(pRoot->children, pRoot);
1038cdf0e10cSrcweir         }
1039cdf0e10cSrcweir         saxify(i_xHandler);
1040cdf0e10cSrcweir     }
1041cdf0e10cSrcweir 
1042cdf0e10cSrcweir     // ::com::sun::star::xml::sax::XFastSAXSerializable
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)1043cdf0e10cSrcweir     void SAL_CALL CDocument::fastSerialize( const Reference< XFastDocumentHandler >& i_xHandler,
1044cdf0e10cSrcweir                                             const Reference< XFastTokenHandler >& i_xTokenHandler,
1045cdf0e10cSrcweir                                             const Sequence< beans::StringPair >& i_rNamespaces,
1046cdf0e10cSrcweir                                             const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& i_rRegisterNamespaces )
1047cdf0e10cSrcweir         throw (SAXException, RuntimeException)
1048cdf0e10cSrcweir     {
1049cdf0e10cSrcweir         ::osl::MutexGuard const g(m_Mutex);
1050cdf0e10cSrcweir 
1051cdf0e10cSrcweir         // add new namespaces to root node
1052cdf0e10cSrcweir         xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr);
1053cdf0e10cSrcweir         if (0 != pRoot) {
1054cdf0e10cSrcweir             const beans::StringPair * pSeq = i_rNamespaces.getConstArray();
1055cdf0e10cSrcweir             for (const beans::StringPair *pNsDef = pSeq;
1056cdf0e10cSrcweir                  pNsDef < pSeq + i_rNamespaces.getLength(); ++pNsDef) {
1057cdf0e10cSrcweir                 OString prefix = OUStringToOString(pNsDef->First,
1058cdf0e10cSrcweir                                     RTL_TEXTENCODING_UTF8);
1059cdf0e10cSrcweir                 OString href   = OUStringToOString(pNsDef->Second,
1060cdf0e10cSrcweir                                     RTL_TEXTENCODING_UTF8);
1061cdf0e10cSrcweir                 // this will only add the ns if it does not exist already
1062cdf0e10cSrcweir                 xmlNewNs(pRoot, reinterpret_cast<const xmlChar*>(href.getStr()),
1063cdf0e10cSrcweir                          reinterpret_cast<const xmlChar*>(prefix.getStr()));
1064cdf0e10cSrcweir             }
1065cdf0e10cSrcweir             // eliminate duplicate namespace declarations
1066cdf0e10cSrcweir             nscleanup(pRoot->children, pRoot);
1067cdf0e10cSrcweir         }
1068cdf0e10cSrcweir 
1069cdf0e10cSrcweir         Context aContext(i_xHandler,
1070cdf0e10cSrcweir                          i_xTokenHandler);
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir         // register namespace ids
1073cdf0e10cSrcweir         const beans::Pair<OUString,sal_Int32>* pSeq = i_rRegisterNamespaces.getConstArray();
1074cdf0e10cSrcweir         for (const beans::Pair<OUString,sal_Int32>* pNs = pSeq;
1075cdf0e10cSrcweir              pNs < pSeq + i_rRegisterNamespaces.getLength(); ++pNs)
1076cdf0e10cSrcweir         {
1077cdf0e10cSrcweir             OSL_ENSURE(pNs->Second >= FastToken::NAMESPACE,
1078cdf0e10cSrcweir                        "CDocument::fastSerialize(): invalid NS token id");
1079cdf0e10cSrcweir             aContext.maNamespaceMap[ pNs->First ] = pNs->Second;
1080cdf0e10cSrcweir         }
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir         fastSaxify(aContext);
1083cdf0e10cSrcweir     }
1084cdf0e10cSrcweir }
1085