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