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