337 lines
11 KiB
C++
337 lines
11 KiB
C++
![]() |
/*************************************************************************
|
||
|
*
|
||
|
* $RCSfile: DomExport.cxx,v $
|
||
|
*
|
||
|
* $Revision: 1.2 $
|
||
|
*
|
||
|
* last change: $Author: obo $ $Date: 2004-11-16 10:06:44 $
|
||
|
*
|
||
|
* The Contents of this file are made available subject to the terms of
|
||
|
* either of the following licenses
|
||
|
*
|
||
|
* - GNU Lesser General Public License Version 2.1
|
||
|
* - Sun Industry Standards Source License Version 1.1
|
||
|
*
|
||
|
* Sun Microsystems Inc., October, 2000
|
||
|
*
|
||
|
* GNU Lesser General Public License Version 2.1
|
||
|
* =============================================
|
||
|
* Copyright 2000 by Sun Microsystems, Inc.
|
||
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Lesser General Public
|
||
|
* License version 2.1, as published by the Free Software Foundation.
|
||
|
*
|
||
|
* This library is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public
|
||
|
* License along with this library; if not, write to the Free Software
|
||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||
|
* MA 02111-1307 USA
|
||
|
*
|
||
|
*
|
||
|
* Sun Industry Standards Source License Version 1.1
|
||
|
* =================================================
|
||
|
* The contents of this file are subject to the Sun Industry Standards
|
||
|
* Source License Version 1.1 (the "License"); You may not use this file
|
||
|
* except in compliance with the License. You may obtain a copy of the
|
||
|
* License at http://www.openoffice.org/license.html.
|
||
|
*
|
||
|
* Software provided under this License is provided on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
||
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
||
|
* See the License for the specific provisions governing your rights and
|
||
|
* obligations concerning the Software.
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
||
|
*
|
||
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
||
|
*
|
||
|
* All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s): _______________________________________
|
||
|
*
|
||
|
*
|
||
|
************************************************************************/
|
||
|
|
||
|
#include "DomExport.hxx"
|
||
|
|
||
|
#include "nmspmap.hxx"
|
||
|
#include "xmlexp.hxx"
|
||
|
#include "xmlerror.hxx"
|
||
|
|
||
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
||
|
#include <com/sun/star/uno/Reference.hxx>
|
||
|
#include <com/sun/star/uno/Sequence.hxx>
|
||
|
#include <com/sun/star/xml/dom/XAttr.hpp>
|
||
|
#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
|
||
|
#include <com/sun/star/xml/dom/XNode.hpp>
|
||
|
#include <com/sun/star/xml/dom/XElement.hpp>
|
||
|
#include <com/sun/star/xml/dom/XEntity.hpp>
|
||
|
#include <com/sun/star/xml/dom/XNotation.hpp>
|
||
|
#include <com/sun/star/xml/sax/XAttributeList.hpp>
|
||
|
#include <com/sun/star/xml/dom/NodeType.hpp>
|
||
|
#include <com/sun/star/xml/dom/XNamedNodeMap.hpp>
|
||
|
|
||
|
#include <rtl/ustring.hxx>
|
||
|
#include <rtl/ustrbuf.hxx>
|
||
|
#include <tools/debug.hxx>
|
||
|
|
||
|
#include <unotools/processfactory.hxx>
|
||
|
|
||
|
#include <vector>
|
||
|
|
||
|
|
||
|
using com::sun::star::lang::XMultiServiceFactory;
|
||
|
using com::sun::star::uno::Reference;
|
||
|
using com::sun::star::uno::Sequence;
|
||
|
using com::sun::star::uno::UNO_QUERY;
|
||
|
using com::sun::star::uno::UNO_QUERY_THROW;
|
||
|
using std::vector;
|
||
|
|
||
|
using namespace com::sun::star::xml::dom;
|
||
|
|
||
|
using rtl::OUString;
|
||
|
using rtl::OUStringBuffer;
|
||
|
|
||
|
|
||
|
class DomVisitor
|
||
|
{
|
||
|
public:
|
||
|
DomVisitor() {}
|
||
|
virtual ~DomVisitor() {}
|
||
|
virtual void element( const Reference<XElement>& ) {}
|
||
|
virtual void character( const Reference<XCharacterData>& ) {}
|
||
|
virtual void attribute( const Reference<XAttr>& ) {}
|
||
|
virtual void cdata( const Reference<XCDATASection>& ) {}
|
||
|
virtual void comment( const Reference<XComment>& ) {}
|
||
|
virtual void documentFragment( const Reference<XDocumentFragment>& ) {}
|
||
|
virtual void document( const Reference<XDocument>& ) {}
|
||
|
virtual void documentType( const Reference<XDocumentType>& ) {}
|
||
|
virtual void entity( const Reference<XEntity>& ) {}
|
||
|
virtual void entityReference( const Reference<XEntityReference>& ) {}
|
||
|
virtual void notation( const Reference<XNotation>& ) {}
|
||
|
virtual void processingInstruction( const Reference<XProcessingInstruction>& ) {}
|
||
|
virtual void endElement( const Reference<XElement>& ) {}
|
||
|
};
|
||
|
|
||
|
void visit( DomVisitor&, const Reference<XDocument>& );
|
||
|
void visit( DomVisitor&, const Reference<XNode>& );
|
||
|
|
||
|
|
||
|
|
||
|
void visitNode( DomVisitor& rVisitor, const Reference<XNode>& xNode )
|
||
|
{
|
||
|
switch( xNode->getNodeType() )
|
||
|
{
|
||
|
case NodeType_ATTRIBUTE_NODE:
|
||
|
rVisitor.attribute( Reference<XAttr>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_CDATA_SECTION_NODE:
|
||
|
rVisitor.cdata( Reference<XCDATASection>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_COMMENT_NODE:
|
||
|
rVisitor.comment( Reference<XComment>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_DOCUMENT_FRAGMENT_NODE:
|
||
|
rVisitor.documentFragment( Reference<XDocumentFragment>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_DOCUMENT_NODE:
|
||
|
rVisitor.document( Reference<XDocument>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_DOCUMENT_TYPE_NODE:
|
||
|
rVisitor.documentType( Reference<XDocumentType>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_ELEMENT_NODE:
|
||
|
rVisitor.element( Reference<XElement>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_ENTITY_NODE:
|
||
|
rVisitor.entity( Reference<XEntity>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_ENTITY_REFERENCE_NODE:
|
||
|
rVisitor.entityReference( Reference<XEntityReference>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_NOTATION_NODE:
|
||
|
rVisitor.notation( Reference<XNotation>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_PROCESSING_INSTRUCTION_NODE:
|
||
|
rVisitor.processingInstruction( Reference<XProcessingInstruction>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
case NodeType_TEXT_NODE:
|
||
|
rVisitor.character( Reference<XCharacterData>( xNode, UNO_QUERY_THROW ) );
|
||
|
break;
|
||
|
default:
|
||
|
DBG_ERROR( "unknown DOM node type" );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void visit( DomVisitor& rVisitor, const Reference<XDocument>& xDocument )
|
||
|
{
|
||
|
visit( rVisitor, Reference<XNode>( xDocument, UNO_QUERY_THROW ) );
|
||
|
}
|
||
|
|
||
|
void visit( DomVisitor& rVisitor, const Reference<XNode>& xNode )
|
||
|
{
|
||
|
visitNode( rVisitor, xNode );
|
||
|
for( Reference<XNode> xChild = xNode->getFirstChild();
|
||
|
xChild.is();
|
||
|
xChild = xChild->getNextSibling() )
|
||
|
{
|
||
|
visit( rVisitor, xChild );
|
||
|
}
|
||
|
if( xNode->getNodeType() == NodeType_ELEMENT_NODE )
|
||
|
rVisitor.endElement( Reference<XElement>( xNode, UNO_QUERY_THROW ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
class DomExport: public DomVisitor
|
||
|
{
|
||
|
SvXMLExport& mrExport;
|
||
|
vector<SvXMLNamespaceMap> maNamespaces;
|
||
|
|
||
|
void pushNamespace();
|
||
|
void popNamespace();
|
||
|
void addNamespace( const OUString& sPrefix, const OUString& sURI );
|
||
|
OUString qualifiedName( const OUString& sPrefix, const OUString& sURI,
|
||
|
const OUString& sLocalName );
|
||
|
OUString qualifiedName( const Reference<XNode>& );
|
||
|
OUString qualifiedName( const Reference<XElement>& );
|
||
|
OUString qualifiedName( const Reference<XAttr>& );
|
||
|
void addAttribute( const Reference<XAttr>& );
|
||
|
|
||
|
public:
|
||
|
|
||
|
DomExport( SvXMLExport& rExport );
|
||
|
virtual ~DomExport();
|
||
|
|
||
|
virtual void element( const Reference<XElement>& );
|
||
|
virtual void endElement( const Reference<XElement>& );
|
||
|
virtual void character( const Reference<XCharacterData>& );
|
||
|
};
|
||
|
|
||
|
DomExport::DomExport( SvXMLExport& rExport ) :
|
||
|
mrExport( rExport )
|
||
|
{
|
||
|
maNamespaces.push_back( rExport.GetNamespaceMap() );
|
||
|
}
|
||
|
|
||
|
DomExport::~DomExport()
|
||
|
{
|
||
|
DBG_ASSERT( maNamespaces.size() == 1, "namespace missing" );
|
||
|
maNamespaces.clear();
|
||
|
}
|
||
|
|
||
|
void DomExport::pushNamespace()
|
||
|
{
|
||
|
maNamespaces.push_back( maNamespaces.back() );
|
||
|
}
|
||
|
|
||
|
void DomExport::popNamespace()
|
||
|
{
|
||
|
maNamespaces.pop_back();
|
||
|
}
|
||
|
|
||
|
void DomExport::addNamespace( const OUString& sPrefix, const OUString& sURI )
|
||
|
{
|
||
|
SvXMLNamespaceMap& rMap = maNamespaces.back();
|
||
|
sal_uInt16 nKey = rMap.GetKeyByPrefix( sPrefix );
|
||
|
|
||
|
// we need to register the namespace, if either the prefix isn't known or
|
||
|
// is used for a different namespace
|
||
|
if( nKey == XML_NAMESPACE_UNKNOWN ||
|
||
|
rMap.GetNameByKey( nKey ) != sURI )
|
||
|
{
|
||
|
// add prefix to map, and add declaration
|
||
|
rMap.Add( sPrefix, sURI );
|
||
|
mrExport.AddAttribute(
|
||
|
OUString( RTL_CONSTASCII_USTRINGPARAM( "xmlns:" ) ) + sPrefix,
|
||
|
sURI );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
OUString DomExport::qualifiedName( const OUString& sPrefix,
|
||
|
const OUString& sURI,
|
||
|
const OUString& sLocalName )
|
||
|
{
|
||
|
OUStringBuffer sBuffer;
|
||
|
if( ( sPrefix.getLength() > 0 ) && ( sURI.getLength() > 0 ) )
|
||
|
{
|
||
|
addNamespace( sPrefix, sURI );
|
||
|
sBuffer.append( sPrefix );
|
||
|
sBuffer.append( sal_Unicode( ':' ) );
|
||
|
}
|
||
|
sBuffer.append( sLocalName );
|
||
|
return sBuffer.makeStringAndClear();
|
||
|
}
|
||
|
|
||
|
OUString DomExport::qualifiedName( const Reference<XNode>& xNode )
|
||
|
{
|
||
|
return qualifiedName( xNode->getPrefix(), xNode->getNamespaceURI(),
|
||
|
xNode->getNodeName() );
|
||
|
}
|
||
|
|
||
|
OUString DomExport::qualifiedName( const Reference<XElement>& xElement )
|
||
|
{
|
||
|
return qualifiedName( xElement->getPrefix(), xElement->getNamespaceURI(),
|
||
|
xElement->getNodeName() );
|
||
|
}
|
||
|
|
||
|
OUString DomExport::qualifiedName( const Reference<XAttr>& xAttr )
|
||
|
{
|
||
|
return qualifiedName( xAttr->getPrefix(), xAttr->getNamespaceURI(),
|
||
|
xAttr->getNodeName() );
|
||
|
}
|
||
|
|
||
|
void DomExport::addAttribute( const Reference<XAttr>& xAttribute )
|
||
|
{
|
||
|
mrExport.AddAttribute( qualifiedName( xAttribute ),
|
||
|
xAttribute->getNodeValue() );
|
||
|
}
|
||
|
|
||
|
void DomExport::element( const Reference<XElement>& xElement )
|
||
|
{
|
||
|
pushNamespace();
|
||
|
|
||
|
// write attributes
|
||
|
Reference<XNamedNodeMap> xAttributes = xElement->getAttributes();
|
||
|
sal_Int32 nLength = xAttributes.is() ? xAttributes->getLength() : 0;
|
||
|
for( sal_Int32 n = 0; n < nLength; n++ )
|
||
|
{
|
||
|
addAttribute( Reference<XAttr>( xAttributes->item( n ), UNO_QUERY_THROW ) );
|
||
|
}
|
||
|
|
||
|
// write name
|
||
|
mrExport.StartElement( qualifiedName( xElement ), sal_False );
|
||
|
}
|
||
|
|
||
|
void DomExport::endElement( const Reference<XElement>& xElement )
|
||
|
{
|
||
|
mrExport.EndElement( qualifiedName( xElement ), sal_False );
|
||
|
popNamespace();
|
||
|
}
|
||
|
|
||
|
void DomExport::character( const Reference<XCharacterData>& xChars )
|
||
|
{
|
||
|
mrExport.Characters( xChars->getNodeValue() );
|
||
|
}
|
||
|
|
||
|
|
||
|
void exportDom( SvXMLExport& rExport, const Reference<XDocument>& xDocument )
|
||
|
{
|
||
|
DomExport aDomExport( rExport );
|
||
|
visit( aDomExport, xDocument );
|
||
|
}
|
||
|
|
||
|
void exportDom( SvXMLExport& rExport, const Reference<XNode>& xNode )
|
||
|
{
|
||
|
DomExport aDomExport( rExport );
|
||
|
visit( aDomExport, xNode );
|
||
|
}
|