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