1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DomExport.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
34 #include "DomExport.hxx"
36 #include <xmloff/nmspmap.hxx>
37 #include <xmloff/xmlexp.hxx>
38 #include "xmlerror.hxx"
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/uno/Reference.hxx>
42 #include <com/sun/star/uno/Sequence.hxx>
43 #include <com/sun/star/xml/dom/XAttr.hpp>
44 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
45 #include <com/sun/star/xml/dom/XNode.hpp>
46 #include <com/sun/star/xml/dom/XElement.hpp>
47 #include <com/sun/star/xml/dom/XEntity.hpp>
48 #include <com/sun/star/xml/dom/XNotation.hpp>
49 #include <com/sun/star/xml/sax/XAttributeList.hpp>
50 #include <com/sun/star/xml/dom/NodeType.hpp>
51 #include <com/sun/star/xml/dom/XNamedNodeMap.hpp>
53 #include <rtl/ustring.hxx>
54 #include <rtl/ustrbuf.hxx>
55 #include <tools/debug.hxx>
57 #include <unotools/processfactory.hxx>
62 using com::sun::star::lang::XMultiServiceFactory
;
63 using com::sun::star::uno::Reference
;
64 using com::sun::star::uno::Sequence
;
65 using com::sun::star::uno::UNO_QUERY
;
66 using com::sun::star::uno::UNO_QUERY_THROW
;
69 using namespace com::sun::star::xml::dom
;
72 using rtl::OUStringBuffer
;
79 virtual ~DomVisitor() {}
80 virtual void element( const Reference
<XElement
>& ) {}
81 virtual void character( const Reference
<XCharacterData
>& ) {}
82 virtual void attribute( const Reference
<XAttr
>& ) {}
83 virtual void cdata( const Reference
<XCDATASection
>& ) {}
84 virtual void comment( const Reference
<XComment
>& ) {}
85 virtual void documentFragment( const Reference
<XDocumentFragment
>& ) {}
86 virtual void document( const Reference
<XDocument
>& ) {}
87 virtual void documentType( const Reference
<XDocumentType
>& ) {}
88 virtual void entity( const Reference
<XEntity
>& ) {}
89 virtual void entityReference( const Reference
<XEntityReference
>& ) {}
90 virtual void notation( const Reference
<XNotation
>& ) {}
91 virtual void processingInstruction( const Reference
<XProcessingInstruction
>& ) {}
92 virtual void endElement( const Reference
<XElement
>& ) {}
95 void visit( DomVisitor
&, const Reference
<XDocument
>& );
96 void visit( DomVisitor
&, const Reference
<XNode
>& );
100 void visitNode( DomVisitor
& rVisitor
, const Reference
<XNode
>& xNode
)
102 switch( xNode
->getNodeType() )
104 case NodeType_ATTRIBUTE_NODE
:
105 rVisitor
.attribute( Reference
<XAttr
>( xNode
, UNO_QUERY_THROW
) );
107 case NodeType_CDATA_SECTION_NODE
:
108 rVisitor
.cdata( Reference
<XCDATASection
>( xNode
, UNO_QUERY_THROW
) );
110 case NodeType_COMMENT_NODE
:
111 rVisitor
.comment( Reference
<XComment
>( xNode
, UNO_QUERY_THROW
) );
113 case NodeType_DOCUMENT_FRAGMENT_NODE
:
114 rVisitor
.documentFragment( Reference
<XDocumentFragment
>( xNode
, UNO_QUERY_THROW
) );
116 case NodeType_DOCUMENT_NODE
:
117 rVisitor
.document( Reference
<XDocument
>( xNode
, UNO_QUERY_THROW
) );
119 case NodeType_DOCUMENT_TYPE_NODE
:
120 rVisitor
.documentType( Reference
<XDocumentType
>( xNode
, UNO_QUERY_THROW
) );
122 case NodeType_ELEMENT_NODE
:
123 rVisitor
.element( Reference
<XElement
>( xNode
, UNO_QUERY_THROW
) );
125 case NodeType_ENTITY_NODE
:
126 rVisitor
.entity( Reference
<XEntity
>( xNode
, UNO_QUERY_THROW
) );
128 case NodeType_ENTITY_REFERENCE_NODE
:
129 rVisitor
.entityReference( Reference
<XEntityReference
>( xNode
, UNO_QUERY_THROW
) );
131 case NodeType_NOTATION_NODE
:
132 rVisitor
.notation( Reference
<XNotation
>( xNode
, UNO_QUERY_THROW
) );
134 case NodeType_PROCESSING_INSTRUCTION_NODE
:
135 rVisitor
.processingInstruction( Reference
<XProcessingInstruction
>( xNode
, UNO_QUERY_THROW
) );
137 case NodeType_TEXT_NODE
:
138 rVisitor
.character( Reference
<XCharacterData
>( xNode
, UNO_QUERY_THROW
) );
141 DBG_ERROR( "unknown DOM node type" );
146 void visit( DomVisitor
& rVisitor
, const Reference
<XDocument
>& xDocument
)
148 visit( rVisitor
, Reference
<XNode
>( xDocument
, UNO_QUERY_THROW
) );
151 void visit( DomVisitor
& rVisitor
, const Reference
<XNode
>& xNode
)
153 visitNode( rVisitor
, xNode
);
154 for( Reference
<XNode
> xChild
= xNode
->getFirstChild();
156 xChild
= xChild
->getNextSibling() )
158 visit( rVisitor
, xChild
);
160 if( xNode
->getNodeType() == NodeType_ELEMENT_NODE
)
161 rVisitor
.endElement( Reference
<XElement
>( xNode
, UNO_QUERY_THROW
) );
166 class DomExport
: public DomVisitor
168 SvXMLExport
& mrExport
;
169 vector
<SvXMLNamespaceMap
> maNamespaces
;
171 void pushNamespace();
173 void addNamespace( const OUString
& sPrefix
, const OUString
& sURI
);
174 OUString
qualifiedName( const OUString
& sPrefix
, const OUString
& sURI
,
175 const OUString
& sLocalName
);
176 OUString
qualifiedName( const Reference
<XNode
>& );
177 OUString
qualifiedName( const Reference
<XElement
>& );
178 OUString
qualifiedName( const Reference
<XAttr
>& );
179 void addAttribute( const Reference
<XAttr
>& );
183 DomExport( SvXMLExport
& rExport
);
184 virtual ~DomExport();
186 virtual void element( const Reference
<XElement
>& );
187 virtual void endElement( const Reference
<XElement
>& );
188 virtual void character( const Reference
<XCharacterData
>& );
191 DomExport::DomExport( SvXMLExport
& rExport
) :
194 maNamespaces
.push_back( rExport
.GetNamespaceMap() );
197 DomExport::~DomExport()
199 DBG_ASSERT( maNamespaces
.size() == 1, "namespace missing" );
200 maNamespaces
.clear();
203 void DomExport::pushNamespace()
205 maNamespaces
.push_back( maNamespaces
.back() );
208 void DomExport::popNamespace()
210 maNamespaces
.pop_back();
213 void DomExport::addNamespace( const OUString
& sPrefix
, const OUString
& sURI
)
215 SvXMLNamespaceMap
& rMap
= maNamespaces
.back();
216 sal_uInt16 nKey
= rMap
.GetKeyByPrefix( sPrefix
);
218 // we need to register the namespace, if either the prefix isn't known or
219 // is used for a different namespace
220 if( nKey
== XML_NAMESPACE_UNKNOWN
||
221 rMap
.GetNameByKey( nKey
) != sURI
)
223 // add prefix to map, and add declaration
224 rMap
.Add( sPrefix
, sURI
);
225 mrExport
.AddAttribute(
226 OUString( RTL_CONSTASCII_USTRINGPARAM( "xmlns:" ) ) + sPrefix
,
231 OUString
DomExport::qualifiedName( const OUString
& sPrefix
,
232 const OUString
& sURI
,
233 const OUString
& sLocalName
)
235 OUStringBuffer sBuffer
;
236 if( ( sPrefix
.getLength() > 0 ) && ( sURI
.getLength() > 0 ) )
238 addNamespace( sPrefix
, sURI
);
239 sBuffer
.append( sPrefix
);
240 sBuffer
.append( sal_Unicode( ':' ) );
242 sBuffer
.append( sLocalName
);
243 return sBuffer
.makeStringAndClear();
246 OUString
DomExport::qualifiedName( const Reference
<XNode
>& xNode
)
248 return qualifiedName( xNode
->getPrefix(), xNode
->getNamespaceURI(),
249 xNode
->getNodeName() );
252 OUString
DomExport::qualifiedName( const Reference
<XElement
>& xElement
)
254 return qualifiedName( xElement
->getPrefix(), xElement
->getNamespaceURI(),
255 xElement
->getNodeName() );
258 OUString
DomExport::qualifiedName( const Reference
<XAttr
>& xAttr
)
260 return qualifiedName( xAttr
->getPrefix(), xAttr
->getNamespaceURI(),
261 xAttr
->getNodeName() );
264 void DomExport::addAttribute( const Reference
<XAttr
>& xAttribute
)
266 mrExport
.AddAttribute( qualifiedName( xAttribute
),
267 xAttribute
->getNodeValue() );
270 void DomExport::element( const Reference
<XElement
>& xElement
)
275 Reference
<XNamedNodeMap
> xAttributes
= xElement
->getAttributes();
276 sal_Int32 nLength
= xAttributes
.is() ? xAttributes
->getLength() : 0;
277 for( sal_Int32 n
= 0; n
< nLength
; n
++ )
279 addAttribute( Reference
<XAttr
>( xAttributes
->item( n
), UNO_QUERY_THROW
) );
283 mrExport
.StartElement( qualifiedName( xElement
), sal_False
);
286 void DomExport::endElement( const Reference
<XElement
>& xElement
)
288 mrExport
.EndElement( qualifiedName( xElement
), sal_False
);
292 void DomExport::character( const Reference
<XCharacterData
>& xChars
)
294 mrExport
.Characters( xChars
->getNodeValue() );
298 void exportDom( SvXMLExport
& rExport
, const Reference
<XDocument
>& xDocument
)
300 DomExport
aDomExport( rExport
);
301 visit( aDomExport
, xDocument
);
304 void exportDom( SvXMLExport
& rExport
, const Reference
<XNode
>& xNode
)
306 DomExport
aDomExport( rExport
);
307 visit( aDomExport
, xNode
);