xref: /aoo42x/main/xmloff/source/core/DomExport.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 
31 #include "DomExport.hxx"
32 
33 #include <xmloff/nmspmap.hxx>
34 #include <xmloff/xmlexp.hxx>
35 #include "xmloff/xmlerror.hxx"
36 
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/uno/Reference.hxx>
39 #include <com/sun/star/uno/Sequence.hxx>
40 #include <com/sun/star/xml/dom/XAttr.hpp>
41 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
42 #include <com/sun/star/xml/dom/XNode.hpp>
43 #include <com/sun/star/xml/dom/XElement.hpp>
44 #include <com/sun/star/xml/dom/XEntity.hpp>
45 #include <com/sun/star/xml/dom/XNotation.hpp>
46 #include <com/sun/star/xml/sax/XAttributeList.hpp>
47 #include <com/sun/star/xml/dom/NodeType.hpp>
48 #include <com/sun/star/xml/dom/XNamedNodeMap.hpp>
49 
50 #include <rtl/ustring.hxx>
51 #include <rtl/ustrbuf.hxx>
52 #include <tools/debug.hxx>
53 
54 #include <unotools/processfactory.hxx>
55 
56 #include <vector>
57 
58 
59 using com::sun::star::lang::XMultiServiceFactory;
60 using com::sun::star::uno::Reference;
61 using com::sun::star::uno::Sequence;
62 using com::sun::star::uno::UNO_QUERY;
63 using com::sun::star::uno::UNO_QUERY_THROW;
64 using std::vector;
65 
66 using namespace com::sun::star::xml::dom;
67 
68 using rtl::OUString;
69 using rtl::OUStringBuffer;
70 
71 
72 class DomVisitor
73 {
74 public:
75     DomVisitor() {}
76     virtual ~DomVisitor() {}
77     virtual void element( const Reference<XElement>& ) {}
78     virtual void character( const Reference<XCharacterData>& ) {}
79     virtual void attribute( const Reference<XAttr>& ) {}
80     virtual void cdata( const Reference<XCDATASection>& ) {}
81     virtual void comment( const Reference<XComment>& ) {}
82     virtual void documentFragment( const Reference<XDocumentFragment>& ) {}
83     virtual void document( const Reference<XDocument>& ) {}
84     virtual void documentType( const Reference<XDocumentType>& ) {}
85     virtual void entity( const Reference<XEntity>& ) {}
86     virtual void entityReference( const Reference<XEntityReference>& ) {}
87     virtual void notation( const Reference<XNotation>& ) {}
88     virtual void processingInstruction( const Reference<XProcessingInstruction>& ) {}
89     virtual void endElement( const Reference<XElement>& ) {}
90 };
91 
92 void visit( DomVisitor&, const Reference<XDocument>& );
93 void visit( DomVisitor&, const Reference<XNode>& );
94 
95 
96 
97 void visitNode( DomVisitor& rVisitor, const Reference<XNode>& xNode )
98 {
99     switch( xNode->getNodeType() )
100     {
101     case NodeType_ATTRIBUTE_NODE:
102         rVisitor.attribute( Reference<XAttr>( xNode, UNO_QUERY_THROW ) );
103         break;
104     case NodeType_CDATA_SECTION_NODE:
105         rVisitor.cdata( Reference<XCDATASection>( xNode, UNO_QUERY_THROW ) );
106         break;
107     case NodeType_COMMENT_NODE:
108         rVisitor.comment( Reference<XComment>( xNode, UNO_QUERY_THROW ) );
109         break;
110     case NodeType_DOCUMENT_FRAGMENT_NODE:
111         rVisitor.documentFragment( Reference<XDocumentFragment>( xNode, UNO_QUERY_THROW ) );
112         break;
113     case NodeType_DOCUMENT_NODE:
114         rVisitor.document( Reference<XDocument>( xNode, UNO_QUERY_THROW ) );
115         break;
116     case NodeType_DOCUMENT_TYPE_NODE:
117         rVisitor.documentType( Reference<XDocumentType>( xNode, UNO_QUERY_THROW ) );
118         break;
119     case NodeType_ELEMENT_NODE:
120         rVisitor.element( Reference<XElement>( xNode, UNO_QUERY_THROW ) );
121         break;
122     case NodeType_ENTITY_NODE:
123         rVisitor.entity( Reference<XEntity>( xNode, UNO_QUERY_THROW ) );
124         break;
125     case NodeType_ENTITY_REFERENCE_NODE:
126         rVisitor.entityReference( Reference<XEntityReference>( xNode, UNO_QUERY_THROW ) );
127         break;
128     case NodeType_NOTATION_NODE:
129         rVisitor.notation( Reference<XNotation>( xNode, UNO_QUERY_THROW ) );
130         break;
131     case NodeType_PROCESSING_INSTRUCTION_NODE:
132         rVisitor.processingInstruction( Reference<XProcessingInstruction>( xNode, UNO_QUERY_THROW ) );
133         break;
134     case NodeType_TEXT_NODE:
135         rVisitor.character( Reference<XCharacterData>( xNode, UNO_QUERY_THROW ) );
136         break;
137     default:
138         DBG_ERROR( "unknown DOM node type" );
139         break;
140     }
141 }
142 
143 void visit( DomVisitor& rVisitor, const Reference<XDocument>& xDocument )
144 {
145     visit( rVisitor, Reference<XNode>( xDocument, UNO_QUERY_THROW ) );
146 }
147 
148 void visit( DomVisitor& rVisitor, const Reference<XNode>& xNode )
149 {
150     visitNode( rVisitor, xNode );
151     for( Reference<XNode> xChild = xNode->getFirstChild();
152          xChild.is();
153          xChild = xChild->getNextSibling() )
154     {
155         visit( rVisitor, xChild );
156     }
157     if( xNode->getNodeType() == NodeType_ELEMENT_NODE )
158         rVisitor.endElement( Reference<XElement>( xNode, UNO_QUERY_THROW ) );
159 }
160 
161 
162 
163 class DomExport: public DomVisitor
164 {
165     SvXMLExport& mrExport;
166     vector<SvXMLNamespaceMap> maNamespaces;
167 
168     void pushNamespace();
169     void popNamespace();
170     void addNamespace( const OUString& sPrefix, const OUString& sURI );
171     OUString qualifiedName( const OUString& sPrefix, const OUString& sURI,
172                             const OUString& sLocalName );
173     OUString qualifiedName( const Reference<XNode>&  );
174     OUString qualifiedName( const Reference<XElement>&  );
175     OUString qualifiedName( const Reference<XAttr>&  );
176     void addAttribute( const Reference<XAttr>& );
177 
178 public:
179 
180     DomExport( SvXMLExport& rExport );
181     virtual ~DomExport();
182 
183     virtual void element( const Reference<XElement>& );
184     virtual void endElement( const Reference<XElement>& );
185     virtual void character( const Reference<XCharacterData>& );
186 };
187 
188 DomExport::DomExport( SvXMLExport& rExport ) :
189     mrExport( rExport )
190 {
191     maNamespaces.push_back( rExport.GetNamespaceMap() );
192 }
193 
194 DomExport::~DomExport()
195 {
196     DBG_ASSERT( maNamespaces.size() == 1, "namespace missing" );
197     maNamespaces.clear();
198 }
199 
200 void DomExport::pushNamespace()
201 {
202     maNamespaces.push_back( maNamespaces.back() );
203 }
204 
205 void DomExport::popNamespace()
206 {
207     maNamespaces.pop_back();
208 }
209 
210 void DomExport::addNamespace( const OUString& sPrefix, const OUString& sURI )
211 {
212     SvXMLNamespaceMap& rMap = maNamespaces.back();
213     sal_uInt16 nKey = rMap.GetKeyByPrefix( sPrefix );
214 
215     // we need to register the namespace, if either the prefix isn't known or
216     // is used for a different namespace
217     if( nKey == XML_NAMESPACE_UNKNOWN  ||
218         rMap.GetNameByKey( nKey ) != sURI )
219     {
220         // add prefix to map, and add declaration
221         rMap.Add( sPrefix, sURI );
222         mrExport.AddAttribute(
223             OUString( RTL_CONSTASCII_USTRINGPARAM( "xmlns:" ) ) + sPrefix,
224             sURI );
225     }
226 }
227 
228 OUString DomExport::qualifiedName( const OUString& sPrefix,
229                                    const OUString& sURI,
230                                    const OUString& sLocalName )
231 {
232     OUStringBuffer sBuffer;
233     if( ( sPrefix.getLength() > 0 ) && ( sURI.getLength() > 0 ) )
234     {
235         addNamespace( sPrefix, sURI );
236         sBuffer.append( sPrefix );
237         sBuffer.append( sal_Unicode( ':' ) );
238     }
239     sBuffer.append( sLocalName );
240     return sBuffer.makeStringAndClear();
241 }
242 
243 OUString DomExport::qualifiedName( const Reference<XNode>& xNode )
244 {
245     return qualifiedName( xNode->getPrefix(), xNode->getNamespaceURI(),
246                           xNode->getNodeName() );
247 }
248 
249 OUString DomExport::qualifiedName( const Reference<XElement>& xElement )
250 {
251     return qualifiedName( xElement->getPrefix(), xElement->getNamespaceURI(),
252                           xElement->getNodeName() );
253 }
254 
255 OUString DomExport::qualifiedName( const Reference<XAttr>& xAttr )
256 {
257     return qualifiedName( xAttr->getPrefix(), xAttr->getNamespaceURI(),
258                           xAttr->getNodeName() );
259 }
260 
261 void DomExport::addAttribute( const Reference<XAttr>& xAttribute )
262 {
263     mrExport.AddAttribute( qualifiedName( xAttribute ),
264                            xAttribute->getNodeValue() );
265 }
266 
267 void DomExport::element( const Reference<XElement>& xElement )
268 {
269     pushNamespace();
270 
271     // write attributes
272     Reference<XNamedNodeMap> xAttributes = xElement->getAttributes();
273     sal_Int32 nLength = xAttributes.is() ? xAttributes->getLength() : 0;
274     for( sal_Int32 n = 0; n < nLength; n++ )
275     {
276         addAttribute( Reference<XAttr>( xAttributes->item( n ), UNO_QUERY_THROW ) );
277     }
278 
279     // write name
280     mrExport.StartElement( qualifiedName( xElement ), sal_False );
281 }
282 
283 void DomExport::endElement( const Reference<XElement>& xElement )
284 {
285     mrExport.EndElement( qualifiedName( xElement ), sal_False );
286     popNamespace();
287 }
288 
289 void DomExport::character( const Reference<XCharacterData>& xChars )
290 {
291     mrExport.Characters( xChars->getNodeValue() );
292 }
293 
294 
295 void exportDom( SvXMLExport& rExport, const Reference<XDocument>& xDocument )
296 {
297     DomExport aDomExport( rExport );
298     visit( aDomExport, xDocument );
299 }
300 
301 void exportDom( SvXMLExport& rExport, const Reference<XNode>& xNode )
302 {
303     DomExport aDomExport( rExport );
304     visit( aDomExport, xNode );
305 }
306