ScXMLTableRowCellContext implements fast interfaces:

Implementation of fast interfaces for contexts in path from
ScXMLImport::CreateFastContext to ScXMLTableRowCellContext.
FastParser is enabled and duplicates are avoided at all
possible places.
OOoXML filters still need those legacy paths we removed,
so I had to temporarily map them to fast elements, which
would increase their load time, but hopefully it should
help us in the long run.

Change-Id: Ie997a9a8b72787da2356abc99ea2cd57c2e5b670
Reviewed-on: https://gerrit.libreoffice.org/28648
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
diff --git a/filter/source/odfflatxml/OdfFlatXml.cxx b/filter/source/odfflatxml/OdfFlatXml.cxx
index f8744ee..f39fc00 100644
--- a/filter/source/odfflatxml/OdfFlatXml.cxx
+++ b/filter/source/odfflatxml/OdfFlatXml.cxx
@@ -29,6 +29,7 @@
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#include <com/sun/star/xml/sax/SAXException.hpp>
#include <com/sun/star/xml/sax/Writer.hpp>
#include <com/sun/star/xml/sax/XFastParser.hpp>

#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
@@ -142,6 +143,8 @@ OdfFlatXml::importer(
    inputSource.sSystemId = url;
    inputSource.sPublicId = url;
    inputSource.aInputStream = inputStream;
    css::uno::Reference< css::xml::sax::XFastParser > xFastParser = dynamic_cast<
                            css::xml::sax::XFastParser* >( docHandler.get() );
    saxParser->setDocumentHandler(docHandler);
    try
    {
@@ -149,7 +152,10 @@ OdfFlatXml::importer(
        if ( xSeekable.is() )
            xSeekable->seek( 0 );

        saxParser->parseStream(inputSource);
        if( xFastParser.is() )
            xFastParser->parseStream( inputSource );
        else
            saxParser->parseStream(inputSource);
    }
    catch (const Exception &exc)
    {
diff --git a/filter/source/xsltfilter/XSLTFilter.cxx b/filter/source/xsltfilter/XSLTFilter.cxx
index 38dbb8a..468757f 100644
--- a/filter/source/xsltfilter/XSLTFilter.cxx
+++ b/filter/source/xsltfilter/XSLTFilter.cxx
@@ -42,6 +42,7 @@
#include <com/sun/star/xml/sax/InputSource.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#include <com/sun/star/xml/sax/XFastParser.hpp>
#include <com/sun/star/xml/sax/SAXException.hpp>
#include <com/sun/star/xml/sax/Writer.hpp>
#include <com/sun/star/xml/XImportFilter.hpp>
@@ -357,6 +358,8 @@ namespace XSLT

                        // set doc handler
                        xSaxParser->setDocumentHandler(xHandler);
                        css::uno::Reference< css::xml::sax::XFastParser > xFastParser = dynamic_cast<
                            css::xml::sax::XFastParser* >( xHandler.get() );

                        // transform
                        m_tcontrol->start();
@@ -388,7 +391,10 @@ namespace XSLT
                                result = m_cTransformed.wait(&timeout);
                        };
                        if (!m_bError) {
                                xSaxParser->parseStream(aInput);
                                if( xFastParser.is() )
                                    xFastParser->parseStream( aInput );
                                else
                                    xSaxParser->parseStream( aInput );
                        }
                        m_tcontrol->terminate();
                        return !m_bError;
diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx
index e4b7cd5..0208b3da 100644
--- a/include/xmloff/xmlimp.hxx
+++ b/include/xmloff/xmlimp.hxx
@@ -570,6 +570,7 @@ public:
    virtual void NotifyEmbeddedFontRead() {};

    bool needFixPositionAfterZ() const;
    const css::uno::Reference< css::xml::sax::XFastNamespaceHandler > getNamespaceHandler() { return maNamespaceHandler.get(); }
};

inline rtl::Reference< XMLTextImportHelper > const & SvXMLImport::GetTextImport()
diff --git a/include/xmloff/xmlmetai.hxx b/include/xmloff/xmlmetai.hxx
index 1ae3cec..3aab9d1 100644
--- a/include/xmloff/xmlmetai.hxx
+++ b/include/xmloff/xmlmetai.hxx
@@ -44,6 +44,9 @@ public:
        const OUString& rLName,
        const css::uno::Reference< css::document::XDocumentProperties>& xDocProps);

    SvXMLMetaDocumentContext(SvXMLImport& rImport, sal_Int32 nElement,
        const css::uno::Reference< css::document::XDocumentProperties>& xDocProps);

    virtual ~SvXMLMetaDocumentContext() override;

    virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 1698737..989fa33 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -575,6 +575,8 @@ namespace xmloff { namespace token {
        XML_DATE_ADJUST,
        XML_DATE_STYLE,
        XML_DATE_TIME,
        XML_DATE_TIME_UPDATE,
        XML_DATE_TIME_VISIBLE,
        XML_DATE_VALUE,
        XML_DATETIME,
        XML_DAY,
@@ -846,6 +848,7 @@ namespace xmloff { namespace token {
        XML_FOOTER_FIRST,
        XML_FOOTER_LEFT,
        XML_FOOTER_STYLE,
        XML_FOOTER_VISIBLE,
        XML_FOOTNOTE,
        XML_FOOTNOTE_BODY,
        XML_FOOTNOTE_CITATION,
@@ -1378,6 +1381,7 @@ namespace xmloff { namespace token {
        XML_PAGE_MASTER_NAME,
        XML_PAGE_NAME,
        XML_PAGE_NUMBER,
        XML_PAGE_NUMBER_VISIBLE,
        XML_PAGE_START_MARGIN,
        XML_PAGE_STYLE_NAME,
        XML_PAGE_THUMBNAIL,
diff --git a/sc/source/filter/xml/XMLEmptyContext.cxx b/sc/source/filter/xml/XMLEmptyContext.cxx
index 8e7abc8..f108b43 100644
--- a/sc/source/filter/xml/XMLEmptyContext.cxx
+++ b/sc/source/filter/xml/XMLEmptyContext.cxx
@@ -21,9 +21,8 @@
#include "xmlimprt.hxx"

ScXMLEmptyContext::ScXMLEmptyContext( ScXMLImport& rImport,
                                      sal_uInt16 nPrfx,
                                      const OUString& rLName) :
    ScXMLImportContext( rImport, nPrfx, rLName )
                                      sal_Int32 /*nElement*/ ) :
    ScXMLImportContext( rImport )
{
}

@@ -31,17 +30,14 @@ ScXMLEmptyContext::~ScXMLEmptyContext()
{
}

SvXMLImportContext *ScXMLEmptyContext::CreateChildContext( sal_uInt16 nPrefix,
                                            const OUString& rLName,
                                            const css::uno::Reference<css::xml::sax::XAttributeList>& /* xAttrList */ )
css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
    ScXMLEmptyContext::createFastChildContext( sal_Int32 nElement,
    const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ )
    throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception)
{
    SvXMLImportContext *pContext = new ScXMLEmptyContext(GetScImport(), nPrefix, rLName);
    SvXMLImportContext *pContext = new ScXMLEmptyContext( GetScImport(), nElement );

    return pContext;
}

void ScXMLEmptyContext::EndElement()
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/XMLEmptyContext.hxx b/sc/source/filter/xml/XMLEmptyContext.hxx
index 2587885..e003cde 100644
--- a/sc/source/filter/xml/XMLEmptyContext.hxx
+++ b/sc/source/filter/xml/XMLEmptyContext.hxx
@@ -27,16 +27,14 @@
class ScXMLEmptyContext : public ScXMLImportContext
{
public:
    ScXMLEmptyContext( ScXMLImport& rImport, sal_uInt16 nPrfx,
                        const OUString& rLName);
    ScXMLEmptyContext( ScXMLImport& rImport, sal_Int32 nElement );

    virtual ~ScXMLEmptyContext() override;

    virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
                                     const OUString& rLocalName,
                                     const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList ) override;

    virtual void EndElement() override;
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
        createFastChildContext( sal_Int32 nElement,
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception ) override;
};

#endif
diff --git a/sc/source/filter/xml/importcontext.cxx b/sc/source/filter/xml/importcontext.cxx
index 9e851c6..56196ea 100644
--- a/sc/source/filter/xml/importcontext.cxx
+++ b/sc/source/filter/xml/importcontext.cxx
@@ -15,6 +15,11 @@ ScXMLImportContext::ScXMLImportContext(ScXMLImport& rImport, sal_uInt16 nPrefix,
{
}

ScXMLImportContext::ScXMLImportContext(SvXMLImport& rImport ) :
    SvXMLImportContext( rImport )
{
}

ScXMLImport& ScXMLImportContext::GetScImport()
{
    return static_cast<ScXMLImport&>(GetImport());
@@ -25,4 +30,19 @@ const ScXMLImport& ScXMLImportContext::GetScImport() const
    return static_cast<const ScXMLImport&>(GetImport());
}

void SAL_CALL ScXMLImportContext::startFastElement(sal_Int32 /*nElement*/, const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/)
    throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception)
{
}

void SAL_CALL ScXMLImportContext::endFastElement(sal_Int32 /*nElement*/)
    throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception)
{
}

void SAL_CALL ScXMLImportContext::characters(const OUString &)
    throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception)
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/importcontext.hxx b/sc/source/filter/xml/importcontext.hxx
index 6b660631..0d9a136 100644
--- a/sc/source/filter/xml/importcontext.hxx
+++ b/sc/source/filter/xml/importcontext.hxx
@@ -24,6 +24,18 @@ public:
    ScXMLImportContext(
        ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLocalName);

    ScXMLImportContext( SvXMLImport& rImport );

    virtual void SAL_CALL startFastElement (sal_Int32 nElement,
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

    virtual void SAL_CALL characters(const OUString & aChars)
            throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

    virtual void SAL_CALL endFastElement(sal_Int32 nElement)
            throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

protected:
    ScXMLImport& GetScImport();
    const ScXMLImport& GetScImport() const;
diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx
index 17cc879..f31079d 100644
--- a/sc/source/filter/xml/xmlbodyi.cxx
+++ b/sc/source/filter/xml/xmlbodyi.cxx
@@ -41,6 +41,7 @@
#include "scerrors.hxx"
#include "tabprotection.hxx"
#include "datastreamimport.hxx"
#include <sax/fastattribs.hxx>

#include <xmloff/xmltkmap.hxx>
#include <xmloff/xmltoken.hxx>
@@ -56,10 +57,9 @@ using namespace com::sun::star;
using namespace xmloff::token;

ScXMLBodyContext::ScXMLBodyContext( ScXMLImport& rImport,
                                              sal_uInt16 nPrfx,
                                                   const OUString& rLName,
                                              const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
    ScXMLImportContext( rImport, nPrfx, rLName ),
                                    sal_Int32 /*nElement*/,
                                    const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
    ScXMLImportContext( rImport ),
    sPassword(),
    meHash1(PASSHASH_SHA1),
    meHash2(PASSHASH_UNSPECIFIED),
@@ -90,30 +90,35 @@ ScXMLBodyContext::ScXMLBodyContext( ScXMLImport& rImport,
        pDoc->SetStorageGrammar( eGrammar);
    }

    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; ++i )
    {
        const OUString& sAttrName(xAttrList->getNameByIndex( i ));
        OUString aLocalName;
        sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
                                            sAttrName, &aLocalName );
        const OUString& sValue(xAttrList->getValueByIndex( i ));
    if( !xAttrList.is() )
        return;

        if (nPrefix == XML_NAMESPACE_TABLE)
    sax_fastparser::FastAttributeList *pAttribList;
    assert( dynamic_cast< sax_fastparser::FastAttributeList *>( xAttrList.get() ) != nullptr );
    pAttribList = static_cast< sax_fastparser::FastAttributeList *>( xAttrList.get() );

    const std::vector< sal_Int32 >& rAttrList = pAttribList->getFastAttributeTokens();
    for ( size_t i = 0; i < rAttrList.size(); i++ )
    {
        sal_Int32 nToken = rAttrList[ i ];
        const OUString sValue = OUString(pAttribList->getFastAttributeValue(i),
                                    pAttribList->AttributeValueLength(i), RTL_TEXTENCODING_UTF8);
        if( NAMESPACE_TOKEN( XML_NAMESPACE_TABLE ) == ( nToken & NMSP_MASK ) )
        {
            if (IsXMLToken(aLocalName, XML_STRUCTURE_PROTECTED))
            const sal_Int32 nLocalToken = nToken & TOKEN_MASK;
            if( nLocalToken == XML_STRUCTURE_PROTECTED )
                bProtected = IsXMLToken(sValue, XML_TRUE);
            else if (IsXMLToken(aLocalName, XML_PROTECTION_KEY))
            else if ( nLocalToken == XML_PROTECTION_KEY )
                sPassword = sValue;
            else if (IsXMLToken(aLocalName, XML_PROTECTION_KEY_DIGEST_ALGORITHM))
                meHash1 = ScPassHashHelper::getHashTypeFromURI(sValue);
            else if (IsXMLToken(aLocalName, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2))
                meHash2 = ScPassHashHelper::getHashTypeFromURI(sValue);
            else if (  nLocalToken == XML_PROTECTION_KEY_DIGEST_ALGORITHM )
                meHash1 = ScPassHashHelper::getHashTypeFromURI( sValue );
            else if (  nLocalToken == XML_PROTECTION_KEY_DIGEST_ALGORITHM_2 )
                meHash2 = ScPassHashHelper::getHashTypeFromURI( sValue );
        }
        else if(nPrefix == XML_NAMESPACE_LO_EXT)
        else if ( nToken == ( NAMESPACE_TOKEN( XML_NAMESPACE_LO_EXT ) |
                                        XML_PROTECTION_KEY_DIGEST_ALGORITHM_2 ) )
        {
            if (IsXMLToken(aLocalName, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2))
                meHash2 = ScPassHashHelper::getHashTypeFromURI(sValue);
            meHash2 = ScPassHashHelper::getHashTypeFromURI( sValue );
        }
    }
}
@@ -154,18 +159,6 @@ SvXMLImportContext *ScXMLBodyContext::CreateChildContext( sal_uInt16 nPrefix,
    case XML_TOK_BODY_LABEL_RANGES:
        pContext = new ScXMLLabelRangesContext( GetScImport(), nPrefix, rLocalName, xAttrList );
        break;
    case XML_TOK_BODY_TABLE:
        if (GetScImport().GetTables().GetCurrentSheet() >= MAXTAB)
        {
            GetScImport().SetRangeOverflowType(SCWARN_IMPORT_SHEET_OVERFLOW);
            pContext = new ScXMLEmptyContext(GetScImport(), nPrefix, rLocalName);
        }
        else
        {
            pContext = new ScXMLTableContext( GetScImport(),nPrefix, rLocalName,
                                              xAttrList );
        }
        break;
    case XML_TOK_BODY_NAMED_EXPRESSIONS:
        pContext = new ScXMLNamedExpressionsContext (
            GetScImport(), nPrefix, rLocalName, xAttrList,
@@ -202,7 +195,49 @@ SvXMLImportContext *ScXMLBodyContext::CreateChildContext( sal_uInt16 nPrefix,
    return pContext;
}

void ScXMLBodyContext::Characters( const OUString& )
uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
        ScXMLBodyContext::createFastChildContext( sal_Int32 nElement,
        const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
        throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData();
    if ( pSheetData && pSheetData->HasStartPos() )
    {
        // stream part to copy ends before the next child element
        sal_Int32 nEndOffset = GetScImport().GetByteOffset();
        pSheetData->EndStreamPos( nEndOffset );
    }

    SvXMLImportContext *pContext = nullptr;

    const SvXMLTokenMap& rTokenMap = GetScImport().GetBodyElemTokenMap();
    switch( rTokenMap.Get( nElement ) )
    {
    case XML_TOK_BODY_TABLE:
        if (GetScImport().GetTables().GetCurrentSheet() >= MAXTAB)
        {
            GetScImport().SetRangeOverflowType(SCWARN_IMPORT_SHEET_OVERFLOW);
            pContext = new ScXMLEmptyContext(GetScImport(), nElement );
        }
        else
        {
            pContext = new ScXMLTableContext( GetScImport(),nElement, xAttrList );
        }
        break;

    // TODO: handle all other cases
    default:
        pContext = new SvXMLImportContext( GetImport() );
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport() );

    return pContext;
}

void SAL_CALL ScXMLBodyContext::characters(const OUString &)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData();
    if ( pSheetData && pSheetData->HasStartPos() )
@@ -214,7 +249,8 @@ void ScXMLBodyContext::Characters( const OUString& )
    // otherwise ignore
}

void ScXMLBodyContext::EndElement()
void SAL_CALL ScXMLBodyContext::endFastElement(sal_Int32 /*nElement*/)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData();
    if ( pSheetData && pSheetData->HasStartPos() )
diff --git a/sc/source/filter/xml/xmlbodyi.hxx b/sc/source/filter/xml/xmlbodyi.hxx
index ac9274b..b5176cc 100644
--- a/sc/source/filter/xml/xmlbodyi.hxx
+++ b/sc/source/filter/xml/xmlbodyi.hxx
@@ -40,15 +40,26 @@ class ScXMLBodyContext : public ScXMLImportContext
    ScXMLChangeTrackingImportHelper*    pChangeTrackingImportHelper;

public:
    ScXMLBodyContext( ScXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
                        const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList );

    ScXMLBodyContext( ScXMLImport& rImport, sal_Int32 nElement,
                        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList );

    virtual ~ScXMLBodyContext() override;

    virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
                                                    const OUString& rLocalName,
                                                    const css::uno::Reference< css::xml::sax::XAttributeList>& xAttrList ) override;
    virtual void EndElement() override;
    virtual void Characters( const OUString& rChars ) override;

    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
        createFastChildContext( sal_Int32 nElement,
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception ) override;

    virtual void SAL_CALL endFastElement(sal_Int32 nElement)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

    virtual void SAL_CALL characters(const OUString & aChars)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;
};

#endif
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index fb8783c..3559cc8 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -90,6 +90,7 @@
#include <svl/sharedstringpool.hxx>
#include <svtools/miscopt.hxx>
#include <sax/tools/converter.hxx>
#include <sax/fastattribs.hxx>

#include <com/sun/star/util/NumberFormat.hpp>
#include <com/sun/star/util/Date.hpp>
@@ -116,12 +117,11 @@ ScXMLTableRowCellContext::Field::~Field()
}

ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
                                      sal_uInt16 nPrfx,
                                      const OUString& rLName,
                                      const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList,
                                      sal_Int32 /*nElement*/,
                                      const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
                                      const bool bTempIsCovered,
                                      const sal_Int32 nTempRepeatedRows ) :
    ScXMLImportContext(rImport, nPrfx, rLName),
    ScXMLImportContext( rImport ),
    mpEditEngine(GetScImport().GetEditEngine()),
    mnCurParagraph(0),
    pDetectiveObjVec(nullptr),
@@ -155,136 +155,142 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,

    rXMLImport.SetRemoveLastChar(false);
    rXMLImport.GetTables().AddColumn(bTempIsCovered);
    const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    OUString aLocalName;

    std::unique_ptr<OUString> xStyleName;
    std::unique_ptr<OUString> xCurrencySymbol;
    const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
    for (sal_Int16 i = 0; i < nAttrCount; ++i)
    if( xAttrList.is() )
    {
        sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
            xAttrList->getNameByIndex(i), &aLocalName);
        sax_fastparser::FastAttributeList *pAttribList;
        assert( dynamic_cast< sax_fastparser::FastAttributeList *>( xAttrList.get() ) != nullptr );
        pAttribList = static_cast< sax_fastparser::FastAttributeList *>( xAttrList.get() );

        const OUString& sValue = xAttrList->getValueByIndex(i);
        sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
        switch (nToken)
        const std::vector< sal_Int32 >& rAttrList = pAttribList->getFastAttributeTokens();
        for ( size_t i = 0; i < rAttrList.size(); i++ )
        {
            case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
                xStyleName.reset(new OUString(sValue));
                mbHasStyle = true;
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
                OSL_ENSURE(!maContentValidationName, "here should be only one Validation Name");
                if (!sValue.isEmpty())
                    maContentValidationName.reset(sValue);
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
                bIsMerged = true;
                nMergedRows = static_cast<SCROW>(sValue.toInt32());
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
                bIsMerged = true;
                nMergedCols = static_cast<SCCOL>(sValue.toInt32());
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
                bIsMatrix = true;
                nMatrixCols = static_cast<SCCOL>(sValue.toInt32());
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
                bIsMatrix = true;
                nMatrixRows = static_cast<SCROW>(sValue.toInt32());
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
                nColsRepeated = static_cast<SCCOL>(std::min<sal_Int32>( MAXCOLCOUNT,
                            std::max( sValue.toInt32(), static_cast<sal_Int32>(1) ) ));
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
                nCellType = GetScImport().GetCellType(sValue);
                bIsEmpty = false;
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_NEW_VALUE_TYPE:
                if(sValue == "error")
                    mbErrorValue = true;
                else
            sal_uInt16 nToken = rTokenMap.Get( rAttrList[ i ] );
            const OUString sValue = OUString(pAttribList->getFastAttributeValue(i),
                                    pAttribList->AttributeValueLength(i), RTL_TEXTENCODING_UTF8);
            switch ( nToken )
            {
                case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
                    xStyleName.reset(new OUString(sValue));
                    mbHasStyle = true;
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
                    OSL_ENSURE(!maContentValidationName, "here should be only one Validation Name");
                    if (!sValue.isEmpty())
                        maContentValidationName.reset(sValue);
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
                    bIsMerged = true;
                    nMergedRows = static_cast<SCROW>(sValue.toInt32());
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
                    bIsMerged = true;
                    nMergedCols = static_cast<SCCOL>(sValue.toInt32());
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
                    bIsMatrix = true;
                    nMatrixCols = static_cast<SCCOL>(sValue.toInt32());
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
                    bIsMatrix = true;
                    nMatrixRows = static_cast<SCROW>(sValue.toInt32());
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
                    nColsRepeated = static_cast<SCCOL>(std::min<sal_Int32>( MAXCOLCOUNT,
                                std::max( sValue.toInt32(), static_cast<sal_Int32>(1) ) ));
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
                    nCellType = GetScImport().GetCellType(sValue);
                bIsEmpty = false;
                mbNewValueType = true;
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
            {
                if (!sValue.isEmpty())
                {
                    ::sax::Converter::convertDouble(fValue, sValue);
                    bIsEmpty = false;

                    //if office:value="0", let's get the text:p in case this is
                    //a special case in HasSpecialCaseFormulaText(). If it
                    //turns out not to be a special case, we'll use the 0 value.
                    if(fValue == 0.0)
                        bFormulaTextResult = true;
                }
            }
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
            {
                if (!sValue.isEmpty() && rXMLImport.SetNullDateOnUnitConverter())
                {
                    rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
                    bIsEmpty = false;
                }
            }
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
            {
                if (!sValue.isEmpty())
                {
                    ::sax::Converter::convertDuration(fValue, sValue);
                    bIsEmpty = false;
                }
            }
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
            {
                if (!sValue.isEmpty())
                {
                    OSL_ENSURE(!maStringValue, "here should be only one string value");
                    maStringValue.reset(sValue);
                    bIsEmpty = false;
                }
            }
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
            {
                if (!sValue.isEmpty())
                {
                    if ( IsXMLToken(sValue, XML_TRUE) )
                        fValue = 1.0;
                    else if ( IsXMLToken(sValue, XML_FALSE) )
                        fValue = 0.0;
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_NEW_VALUE_TYPE:
                    if(sValue == "error")
                        mbErrorValue = true;
                    else
                        ::sax::Converter::convertDouble(fValue, sValue);
                        nCellType = GetScImport().GetCellType(sValue);
                    bIsEmpty = false;
                }
            }
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
            {
                if (!sValue.isEmpty())
                    mbNewValueType = true;
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
                {
                    OSL_ENSURE(!maFormula, "here should be only one formula");
                    OUString aFormula, aFormulaNmsp;
                    rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue );
                    maFormula.reset( FormulaWithNamespace(aFormula, aFormulaNmsp) );
                    if (!sValue.isEmpty())
                    {
                        ::sax::Converter::convertDouble(fValue, sValue);
                        bIsEmpty = false;

                        //if office:value="0", let's get the text:p in case this is
                        //a special case in HasSpecialCaseFormulaText(). If it
                        //turns out not to be a special case, we'll use the 0 value.
                        if(fValue == 0.0)
                            bFormulaTextResult = true;
                    }
                }
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
                {
                    if (!sValue.isEmpty() && rXMLImport.SetNullDateOnUnitConverter())
                    {
                        rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
                        bIsEmpty = false;
                    }
                }
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
                {
                    if (!sValue.isEmpty())
                    {
                        ::sax::Converter::convertDuration(fValue, sValue);
                        bIsEmpty = false;
                    }
                }
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
                {
                    if (!sValue.isEmpty())
                    {
                        OSL_ENSURE(!maStringValue, "here should be only one string value");
                        maStringValue.reset(sValue);
                        bIsEmpty = false;
                    }
                }
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
                {
                    if (!sValue.isEmpty())
                    {
                        if ( IsXMLToken(sValue, XML_TRUE) )
                            fValue = 1.0;
                        else if ( IsXMLToken(sValue, XML_FALSE) )
                            fValue = 0.0;
                        else
                            ::sax::Converter::convertDouble(fValue, sValue);
                        bIsEmpty = false;
                    }
                }
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
                {
                    if (!sValue.isEmpty())
                    {
                        OSL_ENSURE(!maFormula, "here should be only one formula");
                        OUString aFormula, aFormulaNmsp;
                        rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue );
                        maFormula.reset( FormulaWithNamespace(aFormula, aFormulaNmsp) );
                    }
                }
                break;
                case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
                    xCurrencySymbol.reset(new OUString(sValue));
                break;
                default:
                    ;
            }
            break;
            case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
                xCurrencySymbol.reset(new OUString(sValue));
            break;
            default:
                ;
        }
    }

    if (maFormula)
    {
        if (nCellType == util::NumberFormat::TEXT)
@@ -1490,7 +1496,8 @@ bool ScXMLTableRowCellContext::IsPossibleErrorString() const
            GetScImport().GetFormulaErrorConstant(*maStringValue) != FormulaError::NONE);
}

void ScXMLTableRowCellContext::EndElement()
void SAL_CALL ScXMLTableRowCellContext::endFastElement(sal_Int32 /*nElement*/)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    HasSpecialCaseFormulaText();
    if( bFormulaTextResult && (mbPossibleErrorCell || mbCheckWithCompilerForError) )
diff --git a/sc/source/filter/xml/xmlcelli.hxx b/sc/source/filter/xml/xmlcelli.hxx
index 39bb757..845bdc0 100644
--- a/sc/source/filter/xml/xmlcelli.hxx
+++ b/sc/source/filter/xml/xmlcelli.hxx
@@ -129,9 +129,8 @@ class ScXMLTableRowCellContext : public ScXMLImportContext

public:

    ScXMLTableRowCellContext( ScXMLImport& rImport, sal_uInt16 nPrfx,
                       const OUString& rLName,
                       const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList,
    ScXMLTableRowCellContext( ScXMLImport& rImport, sal_Int32 nElement,
                       const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
                       const bool bIsCovered, const sal_Int32 nRepeatedRows );

    virtual ~ScXMLTableRowCellContext() override;
@@ -151,7 +150,8 @@ public:
    void SetDetectiveObj( const ScAddress& rPosition );
    void SetCellRangeSource( const ScAddress& rPosition );

    virtual void EndElement() override;
    virtual void SAL_CALL endFastElement(sal_Int32 nElement)
            throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;
};

#endif
diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx
index c798e19..bb47480 100644
--- a/sc/source/filter/xml/xmlimprt.cxx
+++ b/sc/source/filter/xml/xmlimprt.cxx
@@ -73,6 +73,7 @@
#include "editattributemap.hxx"
#include "documentimport.hxx"
#include "pivotsource.hxx"
#include "importcontext.hxx"
#include <unonames.hxx>
#include <numformat.hxx>

@@ -233,9 +234,28 @@ public:
        const OUString& rLName,
        const uno::Reference<xml::sax::XAttributeList>& xAttrList );

    ScXMLDocContext_Impl( ScXMLImport& rImport,
        sal_Int32 nElement,
        const uno::Reference<xml::sax::XFastAttributeList>& xAttrList );

    virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const uno::Reference<xml::sax::XAttributeList>& xAttrList ) override;

    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
        createFastChildContext( sal_Int32 nElement,
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception ) override;

    virtual void SAL_CALL startFastElement (sal_Int32 nElement,
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

    virtual void SAL_CALL characters(const OUString & aChars)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

    virtual void SAL_CALL endFastElement(sal_Int32 nElement)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;
};

ScXMLDocContext_Impl::ScXMLDocContext_Impl( ScXMLImport& rImport, sal_uInt16 nPrfx,
@@ -246,6 +266,12 @@ SvXMLImportContext( rImport, nPrfx, rLName )

}

ScXMLDocContext_Impl::ScXMLDocContext_Impl( ScXMLImport& rImport, sal_Int32 /*nElement*/,
                                           const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/ ) :
SvXMLImportContext( rImport )
{
}

// context for flat file xml format
class ScXMLFlatDocContext_Impl
    : public ScXMLDocContext_Impl, public SvXMLMetaDocumentContext
@@ -256,9 +282,26 @@ public:
        const uno::Reference<xml::sax::XAttributeList>& i_xAttrList,
        const uno::Reference<document::XDocumentProperties>& i_xDocProps);

    ScXMLFlatDocContext_Impl( ScXMLImport& i_rImport,
        sal_Int32 nElement,
        const uno::Reference<xml::sax::XFastAttributeList>& i_xAttrList,
        const uno::Reference<document::XDocumentProperties>& i_xDocProps);

    virtual SvXMLImportContext *CreateChildContext(
        sal_uInt16 i_nPrefix, const OUString& i_rLocalName,
        const uno::Reference<xml::sax::XAttributeList>& i_xAttrList) override;

    virtual void SAL_CALL startFastElement (sal_Int32 nElement,
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

    virtual void SAL_CALL endFastElement(sal_Int32 nElement)
            throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
        createFastChildContext( sal_Int32 nElement,
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception ) override;
};

ScXMLFlatDocContext_Impl::ScXMLFlatDocContext_Impl( ScXMLImport& i_rImport,
@@ -272,6 +315,15 @@ SvXMLMetaDocumentContext(i_rImport, i_nPrefix, i_rLName,
{
}

ScXMLFlatDocContext_Impl::ScXMLFlatDocContext_Impl( ScXMLImport& i_rImport, sal_Int32 nElement,
                                                   const uno::Reference<xml::sax::XFastAttributeList>& i_xAttrList,
                                                   const uno::Reference<document::XDocumentProperties>& i_xDocProps) :
SvXMLImportContext(i_rImport),
ScXMLDocContext_Impl(i_rImport, nElement, i_xAttrList),
SvXMLMetaDocumentContext(i_rImport, nElement, i_xDocProps)
{
}

SvXMLImportContext *ScXMLFlatDocContext_Impl::CreateChildContext(
    sal_uInt16 i_nPrefix, const OUString& i_rLocalName,
    const uno::Reference<xml::sax::XAttributeList>& i_xAttrList)
@@ -287,31 +339,54 @@ SvXMLImportContext *ScXMLFlatDocContext_Impl::CreateChildContext(
    }
}

uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
    ScXMLFlatDocContext_Impl::createFastChildContext( sal_Int32 nElement,
    const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    if ( nElement != ( NAMESPACE_TOKEN( XML_NAMESPACE_OFFICE ) | XML_META ) )
        return ScXMLDocContext_Impl::createFastChildContext( nElement, xAttrList );
    else
        return new SvXMLImportContext( GetImport() );
}

void SAL_CALL ScXMLFlatDocContext_Impl::startFastElement(sal_Int32 nElement,
    const uno::Reference< xml::sax::XFastAttributeList > & xAttrList)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    SvXMLMetaDocumentContext::startFastElement( nElement, xAttrList );
}

void SAL_CALL ScXMLFlatDocContext_Impl::endFastElement(sal_Int32 nElement)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    SvXMLMetaDocumentContext::endFastElement( nElement );
}

class ScXMLBodyContext_Impl : public ScXMLImportContext
{
public:
    ScXMLBodyContext_Impl( ScXMLImport& rImport, sal_uInt16 nPrfx,
        const OUString& rLName,
        const uno::Reference< xml::sax::XAttributeList > & xAttrList );
    ScXMLBodyContext_Impl( ScXMLImport& rImport, sal_Int32 nElement,
        const uno::Reference< xml::sax::XFastAttributeList > & xAttrList );

    virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const uno::Reference< xml::sax::XAttributeList > & xAttrList ) override;
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
        createFastChildContext( sal_Int32 nElement,
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception ) override;
};

ScXMLBodyContext_Impl::ScXMLBodyContext_Impl( ScXMLImport& rImport,
                                             sal_uInt16 nPrfx, const OUString& rLName,
                                             const uno::Reference< xml::sax::XAttributeList > & /* xAttrList */ ) :
ScXMLImportContext( rImport, nPrfx, rLName )
ScXMLBodyContext_Impl::ScXMLBodyContext_Impl( ScXMLImport& rImport, sal_Int32 /*nElement*/,
                                             const uno::Reference< xml::sax::XFastAttributeList > & /* xAttrList */ ) :
ScXMLImportContext( rImport )
{
}

SvXMLImportContext *ScXMLBodyContext_Impl::CreateChildContext(
    sal_uInt16 /* nPrefix */,
    const OUString& rLocalName,
    const uno::Reference< xml::sax::XAttributeList > & xAttrList )
uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
    ScXMLBodyContext_Impl::createFastChildContext( sal_Int32 nElement,
    const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    return GetScImport().CreateBodyContext( rLocalName, xAttrList );
    return GetScImport().CreateBodyContext( nElement, xAttrList );
}

SvXMLImportContext *ScXMLDocContext_Impl::CreateChildContext( sal_uInt16 nPrefix,
@@ -347,11 +422,6 @@ SvXMLImportContext *ScXMLDocContext_Impl::CreateChildContext( sal_uInt16 nPrefix
        if (GetScImport().getImportFlags() & SvXMLImportFlags::SCRIPTS)
            pContext = GetScImport().CreateScriptContext( rLocalName );
        break;
    case XML_TOK_DOC_BODY:
        if (GetScImport().getImportFlags() & SvXMLImportFlags::CONTENT)
            pContext = new ScXMLBodyContext_Impl( GetScImport(), nPrefix,
            rLocalName, xAttrList );
        break;
    case XML_TOK_DOC_SETTINGS:
        if (GetScImport().getImportFlags() & SvXMLImportFlags::SETTINGS)
            pContext = new XMLDocumentSettingsContext(GetScImport(), nPrefix, rLocalName, xAttrList );
@@ -364,6 +434,49 @@ SvXMLImportContext *ScXMLDocContext_Impl::CreateChildContext( sal_uInt16 nPrefix
    return pContext;
}

uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
    ScXMLDocContext_Impl::createFastChildContext( sal_Int32 nElement,
    const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    SvXMLImportContext *pContext(nullptr);

    const SvXMLTokenMap& rTokenMap(GetScImport().GetDocElemTokenMap());
    switch( rTokenMap.Get( nElement ) )
    {
        case XML_TOK_DOC_BODY:
        if (GetScImport().getImportFlags() & SvXMLImportFlags::CONTENT)
            pContext = new ScXMLBodyContext_Impl( GetScImport(),
                                                nElement, xAttrList );
        break;

        //TODO: handle all other cases
        default:
           pContext = new SvXMLImportContext( GetImport() );
    }

    if(!pContext)
        pContext = new SvXMLImportContext( GetImport() );

    return pContext;
}

void SAL_CALL ScXMLDocContext_Impl::startFastElement(sal_Int32 /*nElement*/,
    const uno::Reference< xml::sax::XFastAttributeList > & /*xAttrList*/)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
}

void SAL_CALL ScXMLDocContext_Impl::endFastElement(sal_Int32 /*nElement*/)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
}

void SAL_CALL ScXMLDocContext_Impl::characters(const OUString &)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
}

const SvXMLTokenMap& ScXMLImport::GetDocElemTokenMap()
{
    if( !pDocElemTokenMap )
@@ -1928,13 +2041,7 @@ SvXMLImportContext *ScXMLImport::CreateContext( sal_uInt16 nPrefix,
{
    SvXMLImportContext *pContext = nullptr;

    if( (XML_NAMESPACE_OFFICE == nPrefix) &&
        ( IsXMLToken(rLocalName, XML_DOCUMENT_STYLES) ||
        IsXMLToken(rLocalName, XML_DOCUMENT_CONTENT) ||
        IsXMLToken(rLocalName, XML_DOCUMENT_SETTINGS) )) {
            pContext = new ScXMLDocContext_Impl( *this, nPrefix, rLocalName,
                xAttrList );
    } else if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
    if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
        ( IsXMLToken(rLocalName, XML_DOCUMENT_META)) ) {
            pContext = CreateMetaContext(rLocalName);
    } else if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
@@ -1951,6 +2058,36 @@ SvXMLImportContext *ScXMLImport::CreateContext( sal_uInt16 nPrefix,
    return pContext;
}

SvXMLImportContext *ScXMLImport::CreateFastContext( sal_Int32 nElement,
        const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
{
    SvXMLImportContext *pContext = nullptr;

    switch( nElement )
    {
    case ( NAMESPACE_TOKEN( XML_NAMESPACE_OFFICE ) | XML_DOCUMENT_STYLES ):
    case ( NAMESPACE_TOKEN( XML_NAMESPACE_OFFICE ) | XML_DOCUMENT_CONTENT ):
    case ( NAMESPACE_TOKEN( XML_NAMESPACE_OFFICE ) | XML_DOCUMENT_SETTINGS ):
        pContext = new ScXMLDocContext_Impl( *this, nElement, xAttrList );
        break;

    case ( NAMESPACE_TOKEN( XML_NAMESPACE_OFFICE ) | XML_DOCUMENT ):
    {
        uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
            GetModel(), uno::UNO_QUERY_THROW);
        // flat OpenDocument file format
        pContext = new ScXMLFlatDocContext_Impl( *this, nElement,
            xAttrList, xDPS->getDocumentProperties());
        break;
    }

    default:
        pContext = new SvXMLImportContext( *this );
    }

    return pContext;
}

ScXMLImport::ScXMLImport(
    const css::uno::Reference< css::uno::XComponentContext >& rContext,
    OUString const & implementationName, SvXMLImportFlags nImportFlag)
@@ -2241,10 +2378,10 @@ SvXMLImportContext *ScXMLImport::CreateStylesContext(const OUString& rLocalName,
    return pContext;
}

SvXMLImportContext *ScXMLImport::CreateBodyContext(const OUString& rLocalName,
                                                   const uno::Reference<xml::sax::XAttributeList>& xAttrList)
SvXMLImportContext *ScXMLImport::CreateBodyContext(const sal_Int32 nElement,
                                                   const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
{
    return new ScXMLBodyContext(*this, XML_NAMESPACE_OFFICE, rLocalName, xAttrList);
    return new ScXMLBodyContext(*this, nElement, xAttrList);
}

SvXMLImportContext *ScXMLImport::CreateMetaContext(
diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx
index 28f9ae9..c09dff5 100644
--- a/sc/source/filter/xml/xmlimprt.hxx
+++ b/sc/source/filter/xml/xmlimprt.hxx
@@ -954,6 +954,10 @@ protected:
    virtual SvXMLImportContext *CreateContext(sal_uInt16 nPrefix,
                                      const OUString& rLocalName,
                                      const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList ) override;

    virtual SvXMLImportContext *CreateFastContext( sal_Int32 nElement,
        const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& xAttrList ) override;

    virtual XMLShapeImportHelper* CreateShapeImport() override;

public:
@@ -979,9 +983,10 @@ public:
    SvXMLImportContext *CreateStylesContext(const OUString& rLocalName,
                                     const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList,
                                     bool bAutoStyles );

    SvXMLImportContext *CreateBodyContext(
                                    const OUString& rLocalName,
                                    const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList );
                                    const sal_Int32 nElement,
                                    const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList );

    virtual void SetStatistics( const css::uno::Sequence< css::beans::NamedValue> & i_rStats) override;

diff --git a/sc/source/filter/xml/xmlrowi.cxx b/sc/source/filter/xml/xmlrowi.cxx
index 2a66bde..1308432 100644
--- a/sc/source/filter/xml/xmlrowi.cxx
+++ b/sc/source/filter/xml/xmlrowi.cxx
@@ -33,6 +33,7 @@
#include <xmloff/xmlnmspe.hxx>
#include <xmloff/families.hxx>
#include <xmloff/xmltoken.hxx>
#include <sax/fastattribs.hxx>
#include <com/sun/star/sheet/XSpreadsheet.hpp>
#include <com/sun/star/table/XColumnRowRange.hpp>
#include <com/sun/star/sheet/XPrintAreas.hpp>
@@ -43,55 +44,58 @@ using namespace com::sun::star;
using namespace xmloff::token;

ScXMLTableRowContext::ScXMLTableRowContext( ScXMLImport& rImport,
                                      sal_uInt16 nPrfx,
                                      const OUString& rLName,
                                      const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList ) :
    ScXMLImportContext( rImport, nPrfx, rLName ),
                                      sal_Int32 /*nElement*/,
                                      const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList ) :
    ScXMLImportContext( rImport ),
    sVisibility(GetXMLToken(XML_VISIBLE)),
    nRepeatedRows(1),
    bHasCell(false)
{
    OUString sCellStyleName;
    sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
    const SvXMLTokenMap& rAttrTokenMap(GetScImport().GetTableRowAttrTokenMap());
    for( sal_Int16 i=0; i < nAttrCount; ++i )
    if ( xAttrList.is() )
    {
        const OUString& sAttrName(xAttrList->getNameByIndex( i ));
        OUString aLocalName;
        sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
                                            sAttrName, &aLocalName ));
        const OUString& sValue(xAttrList->getValueByIndex( i ));
        sax_fastparser::FastAttributeList *pAttribList;
        assert( dynamic_cast< sax_fastparser::FastAttributeList *>( xAttrList.get() ) != nullptr );
        pAttribList = static_cast< sax_fastparser::FastAttributeList *>( xAttrList.get() );

        switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
        const std::vector< sal_Int32 >& rAttrList = pAttribList->getFastAttributeTokens();
        for ( size_t i = 0; i < rAttrList.size(); i++ )
        {
            case XML_TOK_TABLE_ROW_ATTR_STYLE_NAME:
            const OUString sValue = OUString(pAttribList->getFastAttributeValue(i),
                                    pAttribList->AttributeValueLength(i), RTL_TEXTENCODING_UTF8);
            switch( rAttrTokenMap.Get( rAttrList[ i ] ) )
            {
                sStyleName = sValue;
                case XML_TOK_TABLE_ROW_ATTR_STYLE_NAME:
                {
                    sStyleName = sValue;
                }
                break;
                case XML_TOK_TABLE_ROW_ATTR_VISIBILITY:
                {
                    sVisibility = sValue;
                }
                break;
                case XML_TOK_TABLE_ROW_ATTR_REPEATED:
                {
                    nRepeatedRows = std::max( sValue.toInt32(), (sal_Int32) 1 );
                    nRepeatedRows = std::min( nRepeatedRows, MAXROWCOUNT );
                }
                break;
                case XML_TOK_TABLE_ROW_ATTR_DEFAULT_CELL_STYLE_NAME:
                {
                    sCellStyleName = sValue;
                }
                break;
                /*case XML_TOK_TABLE_ROW_ATTR_USE_OPTIMAL_HEIGHT:
                {
                    sOptimalHeight = sValue;
                }
                break;*/
            }
            break;
            case XML_TOK_TABLE_ROW_ATTR_VISIBILITY:
            {
                sVisibility = sValue;
            }
            break;
            case XML_TOK_TABLE_ROW_ATTR_REPEATED:
            {
                nRepeatedRows = std::max( sValue.toInt32(), (sal_Int32) 1 );
                nRepeatedRows = std::min( nRepeatedRows, MAXROWCOUNT );
            }
            break;
            case XML_TOK_TABLE_ROW_ATTR_DEFAULT_CELL_STYLE_NAME:
            {
                sCellStyleName = sValue;
            }
            break;
            /*case XML_TOK_TABLE_ROW_ATTR_USE_OPTIMAL_HEIGHT:
            {
                sOptimalHeight = sValue;
            }
            break;*/
        }
    }

    GetScImport().GetTables().AddRow();
    GetScImport().GetTables().SetRowStyle(sCellStyleName);
}
@@ -100,21 +104,22 @@ ScXMLTableRowContext::~ScXMLTableRowContext()
{
}

SvXMLImportContext *ScXMLTableRowContext::CreateChildContext( sal_uInt16 nPrefix,
                                            const OUString& rLName,
                                            const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList )
uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
        ScXMLTableRowContext::createFastChildContext( sal_Int32 nElement,
        const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
        throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    SvXMLImportContext *pContext(nullptr);

    const SvXMLTokenMap& rTokenMap(GetScImport().GetTableRowElemTokenMap());
    switch( rTokenMap.Get( nPrefix, rLName ) )
    switch( rTokenMap.Get( nElement ) )
    {
    case XML_TOK_TABLE_ROW_CELL:
//      if( IsInsertCellPossible() )
        {
            bHasCell = true;
            pContext = new ScXMLTableRowCellContext( GetScImport(), nPrefix,
                                                      rLName, xAttrList, false, static_cast<SCROW>(nRepeatedRows)
            pContext = new ScXMLTableRowCellContext( GetScImport(), nElement,
                                                       xAttrList, false, static_cast<SCROW>(nRepeatedRows)
                                                      //this
                                                      );
        }
@@ -123,8 +128,8 @@ SvXMLImportContext *ScXMLTableRowContext::CreateChildContext( sal_uInt16 nPrefix
//      if( IsInsertCellPossible() )
        {
            bHasCell = true;
            pContext = new ScXMLTableRowCellContext( GetScImport(), nPrefix,
                                                      rLName, xAttrList, true, static_cast<SCROW>(nRepeatedRows)
            pContext = new ScXMLTableRowCellContext( GetScImport(), nElement,
                                                      xAttrList, true, static_cast<SCROW>(nRepeatedRows)
                                                      //this
                                                      );
        }
@@ -132,12 +137,13 @@ SvXMLImportContext *ScXMLTableRowContext::CreateChildContext( sal_uInt16 nPrefix
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
        pContext = new SvXMLImportContext( GetImport() );

    return pContext;
}

void ScXMLTableRowContext::EndElement()
void SAL_CALL ScXMLTableRowContext::endFastElement(sal_Int32 /*nElement*/)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    ScXMLImport& rXMLImport(GetScImport());
    if (!bHasCell && nRepeatedRows > 1)
@@ -209,12 +215,11 @@ void ScXMLTableRowContext::EndElement()
}

ScXMLTableRowsContext::ScXMLTableRowsContext( ScXMLImport& rImport,
                                      sal_uInt16 nPrfx,
                                      const OUString& rLName,
                                      const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList,
                                      sal_Int32 /*nElement*/,
                                      const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
                                      const bool bTempHeader,
                                      const bool bTempGroup ) :
    ScXMLImportContext( rImport, nPrfx, rLName ),
    ScXMLImportContext( rImport ),
    nHeaderStartRow(0),
    nGroupStartRow(0),
    bHeader(bTempHeader),
@@ -232,17 +237,11 @@ ScXMLTableRowsContext::ScXMLTableRowsContext( ScXMLImport& rImport,
    {
        nGroupStartRow = rImport.GetTables().GetCurrentRow();
        ++nGroupStartRow;
        sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
        for( sal_Int16 i=0; i < nAttrCount; ++i )
        if ( xAttrList.is() &&
            xAttrList->hasAttribute( NAMESPACE_TOKEN( XML_NAMESPACE_TABLE ) | XML_DISPLAY ) )
        {
            const OUString& sAttrName(xAttrList->getNameByIndex( i ));
            OUString aLocalName;
            sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
                                                sAttrName, &aLocalName ));
            const OUString& sValue(xAttrList->getValueByIndex( i ));

            if ((nPrefix == XML_NAMESPACE_TABLE) && IsXMLToken(aLocalName, XML_DISPLAY))
                bGroupDisplay = IsXMLToken(sValue, XML_TRUE);
            bGroupDisplay = IsXMLToken( xAttrList->getValue(
                                NAMESPACE_TOKEN( XML_NAMESPACE_TABLE ) | XML_DISPLAY ), XML_TRUE );
        }
    }
}
@@ -251,45 +250,44 @@ ScXMLTableRowsContext::~ScXMLTableRowsContext()
{
}

SvXMLImportContext *ScXMLTableRowsContext::CreateChildContext( sal_uInt16 nPrefix,
                                            const OUString& rLName,
                                            const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList )
uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
        ScXMLTableRowsContext::createFastChildContext( sal_Int32 nElement,
        const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
        throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    SvXMLImportContext *pContext(nullptr);

    const SvXMLTokenMap& rTokenMap(GetScImport().GetTableRowsElemTokenMap());
    switch( rTokenMap.Get( nPrefix, rLName ) )
    switch( rTokenMap.Get( nElement ) )
    {
    case XML_TOK_TABLE_ROWS_ROW_GROUP:
        pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
                                                   rLName, xAttrList,
        pContext = new ScXMLTableRowsContext( GetScImport(), nElement, xAttrList,
                                                   false, true );
        break;
    case XML_TOK_TABLE_ROWS_HEADER_ROWS:
        pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
                                                   rLName, xAttrList,
        pContext = new ScXMLTableRowsContext( GetScImport(), nElement, xAttrList,
                                                   true, false );
        break;
    case XML_TOK_TABLE_ROWS_ROWS:
        pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
                                                   rLName, xAttrList,
        pContext = new ScXMLTableRowsContext( GetScImport(), nElement, xAttrList,
                                                   false, false );
        break;
    case XML_TOK_TABLE_ROWS_ROW:
            pContext = new ScXMLTableRowContext( GetScImport(), nPrefix,
                                                      rLName, xAttrList//,
            pContext = new ScXMLTableRowContext( GetScImport(), nElement,
                                                      xAttrList//,
                                                      //this
                                                      );
        break;
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
        pContext = new SvXMLImportContext( GetImport() );

    return pContext;
}

void ScXMLTableRowsContext::EndElement()
void SAL_CALL ScXMLTableRowsContext::endFastElement(sal_Int32 /*nElement*/)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    ScXMLImport& rXMLImport(GetScImport());
    if (bHeader)
diff --git a/sc/source/filter/xml/xmlrowi.hxx b/sc/source/filter/xml/xmlrowi.hxx
index ea84e9c..5c3ab29 100644
--- a/sc/source/filter/xml/xmlrowi.hxx
+++ b/sc/source/filter/xml/xmlrowi.hxx
@@ -35,17 +35,18 @@ class ScXMLTableRowContext : public ScXMLImportContext

public:

    ScXMLTableRowContext( ScXMLImport& rImport, sal_uInt16 nPrfx,
                       const OUString& rLName,
                       const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList );
    ScXMLTableRowContext( ScXMLImport& rImport, sal_Int32 nElement,
                       const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList );

    virtual ~ScXMLTableRowContext() override;

    virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
                                     const OUString& rLocalName,
                                     const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList ) override;
    virtual void SAL_CALL endFastElement(sal_Int32 nElement)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

    virtual void EndElement() override;
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
        createFastChildContext( sal_Int32 nElement,
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception ) override;
};

class ScXMLTableRowsContext : public ScXMLImportContext
@@ -58,18 +59,20 @@ class ScXMLTableRowsContext : public ScXMLImportContext

public:

    ScXMLTableRowsContext( ScXMLImport& rImport, sal_uInt16 nPrfx,
                       const OUString& rLName,
                       const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList,
    ScXMLTableRowsContext( ScXMLImport& rImport, sal_Int32 nElement,
                       const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
                       const bool bHeader, const bool bGroup);

    virtual ~ScXMLTableRowsContext() override;

    virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
                                     const OUString& rLocalName,
                                     const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList ) override;
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
                        createFastChildContext( sal_Int32 nElement,
                        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
                        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception ) override;

    virtual void EndElement() override;
    virtual void SAL_CALL endFastElement(sal_Int32 nElement)
                        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;

};

#endif
diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx
index 162bacd..6093c52 100644
--- a/sc/source/filter/xml/xmltabi.cxx
+++ b/sc/source/filter/xml/xmltabi.cxx
@@ -42,6 +42,7 @@
#include <xmloff/XMLEventsImportContext.hxx>

#include <tools/urlobj.hxx>
#include <sax/fastattribs.hxx>

using namespace com::sun::star;
using namespace xmloff::token;
@@ -129,10 +130,9 @@ ScXMLExternalTabData::ScXMLExternalTabData() :
}

ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
                                      sal_uInt16 nPrfx,
                                      const OUString& rLName,
                                      const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList ) :
    ScXMLImportContext( rImport, nPrfx, rLName ),
                                      sal_Int32 /*nElement*/,
                                      const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList ) :
    ScXMLImportContext( rImport ),
    nStartOffset(-1),
    bStartFormPage(false),
    bPrintEntireSheet(true)
@@ -143,45 +143,50 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
    ScXMLTabProtectionData aProtectData;
    OUString sName;
    OUString sStyleName;
    sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
    const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableAttrTokenMap();
    for( sal_Int16 i=0; i < nAttrCount; ++i )
    {
        const OUString& sAttrName(xAttrList->getNameByIndex( i ));
        OUString aLocalName;
        sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
                                            sAttrName, &aLocalName ));
        const OUString& sValue(xAttrList->getValueByIndex( i ));

        switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
    if ( xAttrList.is() )
    {
        sax_fastparser::FastAttributeList *pAttribList;
        assert( dynamic_cast< sax_fastparser::FastAttributeList *>( xAttrList.get() ) != nullptr );
        pAttribList = static_cast< sax_fastparser::FastAttributeList *>( xAttrList.get() );

        const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableAttrTokenMap();
        const std::vector< sal_Int32 >& rAttrList = pAttribList->getFastAttributeTokens();
        for ( size_t i = 0; i < rAttrList.size(); i++ )
        {
            case XML_TOK_TABLE_NAME:
                    sName = sValue;
            const OUString sValue = OUString(pAttribList->getFastAttributeValue(i),
                                    pAttribList->AttributeValueLength(i), RTL_TEXTENCODING_UTF8);
            switch( rAttrTokenMap.Get( rAttrList[ i ] ) )
            {
                case XML_TOK_TABLE_NAME:
                        sName = sValue;
                    break;
                case XML_TOK_TABLE_STYLE_NAME:
                        sStyleName = sValue;
                    break;
                case XML_TOK_TABLE_PROTECTED:
                    aProtectData.mbProtected = IsXMLToken(sValue, XML_TRUE);
                break;
            case XML_TOK_TABLE_STYLE_NAME:
                    sStyleName = sValue;
                case XML_TOK_TABLE_PRINT_RANGES:
                        sPrintRanges = sValue;
                    break;
                case XML_TOK_TABLE_PASSWORD:
                    aProtectData.maPassword = sValue;
                break;
            case XML_TOK_TABLE_PROTECTED:
                aProtectData.mbProtected = IsXMLToken(sValue, XML_TRUE);
            break;
            case XML_TOK_TABLE_PRINT_RANGES:
                    sPrintRanges = sValue;
                case XML_TOK_TABLE_PASSHASH:
                    aProtectData.meHash1 = ScPassHashHelper::getHashTypeFromURI( sValue );
                break;
            case XML_TOK_TABLE_PASSWORD:
                aProtectData.maPassword = sValue;
            break;
            case XML_TOK_TABLE_PASSHASH:
                aProtectData.meHash1 = ScPassHashHelper::getHashTypeFromURI(sValue);
            break;
            case XML_TOK_TABLE_PASSHASH_2:
                aProtectData.meHash2 = ScPassHashHelper::getHashTypeFromURI(sValue);
            break;
            case XML_TOK_TABLE_PRINT:
                {
                    if (IsXMLToken(sValue, XML_FALSE))
                        bPrintEntireSheet = false;
                }
                case XML_TOK_TABLE_PASSHASH_2:
                    aProtectData.meHash2 = ScPassHashHelper::getHashTypeFromURI( sValue );
                break;
                case XML_TOK_TABLE_PRINT:
                    {
                        if (IsXMLToken(sValue, XML_FALSE))
                            bPrintEntireSheet = false;
                    }
                    break;
            }

        }
    }

@@ -278,27 +283,6 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( sal_uInt16 nPrefix,
    case XML_TOK_TABLE_PROTECTION_EXT:
        pContext = new ScXMLTableProtectionContext( GetScImport(), nPrefix, rLName, xAttrList );
        break;
    case XML_TOK_TABLE_ROW_GROUP:
        pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
                                                   rLName, xAttrList,
                                                   false, true );
        break;
    case XML_TOK_TABLE_HEADER_ROWS:
        pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
                                                   rLName, xAttrList,
                                                   true, false );
        break;
    case XML_TOK_TABLE_ROWS:
        pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
                                                   rLName, xAttrList,
                                                   false, false );
        break;
    case XML_TOK_TABLE_ROW:
            pContext = new ScXMLTableRowContext( GetScImport(), nPrefix,
                                                      rLName, xAttrList//,
                                                      //this
                                                      );
        break;
    case XML_TOK_TABLE_SOURCE:
        pContext = new ScXMLTableSourceContext( GetScImport(), nPrefix, rLName, xAttrList);
        break;
@@ -336,7 +320,52 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( sal_uInt16 nPrefix,
    return pContext;
}

void ScXMLTableContext::EndElement()
uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
        ScXMLTableContext::createFastChildContext( sal_Int32 nElement,
        const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
        throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
    sal_uInt16 nToken = rTokenMap.Get( nElement );
    if (pExternalRefInfo.get())
    {
        return new SvXMLImportContext( GetImport() );
    }

    SvXMLImportContext *pContext(nullptr);

    switch (nToken)
    {
    case XML_TOK_TABLE_ROW_GROUP:
        pContext = new ScXMLTableRowsContext( GetScImport(), nElement, xAttrList,
                                                   false, true );
        break;
    case XML_TOK_TABLE_HEADER_ROWS:
        pContext = new ScXMLTableRowsContext( GetScImport(), nElement, xAttrList,
                                                   true, false );
        break;
    case XML_TOK_TABLE_ROWS:
        pContext = new ScXMLTableRowsContext( GetScImport(), nElement, xAttrList,
                                                   false, false );
        break;
    case XML_TOK_TABLE_ROW:
            pContext = new ScXMLTableRowContext( GetScImport(), nElement,
                                                      xAttrList//,
                                                      //this
                                                      );
        break;
    default:
        pContext = new SvXMLImportContext( GetImport() );
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport() );

    return pContext;
}

void SAL_CALL ScXMLTableContext::endFastElement(sal_Int32 /*nElement*/)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    ScXMLImport::MutexGuard aMutexGuard(GetScImport());
    ScXMLImport& rImport = GetScImport();
diff --git a/sc/source/filter/xml/xmltabi.hxx b/sc/source/filter/xml/xmltabi.hxx
index a42ecb4..0dfa46d 100644
--- a/sc/source/filter/xml/xmltabi.hxx
+++ b/sc/source/filter/xml/xmltabi.hxx
@@ -48,9 +48,8 @@ class ScXMLTableContext : public ScXMLImportContext

public:

    ScXMLTableContext( ScXMLImport& rImport, sal_uInt16 nPrfx,
                        const OUString& rLName,
                        const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList );
    ScXMLTableContext( ScXMLImport& rImport, sal_Int32 nElement,
                        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList );

    virtual ~ScXMLTableContext() override;

@@ -58,7 +57,13 @@ public:
                                     const OUString& rLocalName,
                                     const css::uno::Reference<css::xml::sax::XAttributeList>& xAttrList ) override;

    virtual void EndElement() override;
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL
        createFastChildContext( sal_Int32 nElement,
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception ) override;

    virtual void SAL_CALL endFastElement(sal_Int32 nElement)
        throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) override;
};

class ScXMLTableProtectionContext : public ScXMLImportContext
diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx
index c6b8be1..ed56083 100644
--- a/sc/source/filter/xml/xmlwrap.cxx
+++ b/sc/source/filter/xml/xmlwrap.cxx
@@ -34,6 +34,7 @@
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/xml/sax/InputSource.hpp>
#include <com/sun/star/xml/sax/Parser.hpp>
#include <com/sun/star/xml/sax/XFastParser.hpp>
#include <com/sun/star/xml/sax/Writer.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
@@ -172,11 +173,16 @@ sal_uInt32 ScXMLImportWrapper::ImportFromComponent(const uno::Reference<uno::XCo
        pImporterImpl->SetPostProcessData(&maPostProcessData);

    // connect parser and filter
    uno::Reference< xml::sax::XFastParser > xFastParser = dynamic_cast<
                            xml::sax::XFastParser* >( xDocHandler.get() );
    xParser->setDocumentHandler( xDocHandler );

    try
    {
        xParser->parseStream( aParserInput );
        if( xFastParser.is() )
            xFastParser->parseStream( aParserInput );
        else
            xParser->parseStream( aParserInput );
    }
    catch( const xml::sax::SAXParseException& r )
    {
diff --git a/xmloff/Library_xof.mk b/xmloff/Library_xof.mk
index 9305128..202a9c2 100644
--- a/xmloff/Library_xof.mk
+++ b/xmloff/Library_xof.mk
@@ -26,6 +26,10 @@ $(eval $(call gb_Library_set_include,xof,\
    $$(INCLUDE) \
))

$(eval $(call gb_Library_use_custom_headers,xof,\
	xmloff/generated \
))

$(eval $(call gb_Library_set_precompiled_header,xof,$(SRCDIR)/xmloff/inc/pch/precompiled_xof))

$(eval $(call gb_Library_use_external,xof,boost_headers))
diff --git a/xmloff/source/core/xmlictxt.cxx b/xmloff/source/core/xmlictxt.cxx
index 4a63be9..05a6c45 100644
--- a/xmloff/source/core/xmlictxt.cxx
+++ b/xmloff/source/core/xmlictxt.cxx
@@ -147,7 +147,11 @@ uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SvXMLImportContext::cre
    (sal_Int32 Element, const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
    throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
    return mrImport.CreateFastContext( Element, Attribs );
    // Call CreateFastContext only if it's the first element of the document
    if ( !mrImport.maFastContexts.size() )
        return mrImport.CreateFastContext( Element, Attribs );
    else
        return new SvXMLImportContext( GetImport() );
}

uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SvXMLImportContext::createUnknownChildContext
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index ed6e22d..9aefba0 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -577,6 +577,8 @@ namespace xmloff { namespace token {
        TOKEN( "date-adjust",                     XML_DATE_ADJUST ),
        TOKEN( "date-style",                      XML_DATE_STYLE ),
        TOKEN( "date-time",                       XML_DATE_TIME ),
        TOKEN( "date-time-update",                XML_DATE_TIME_UPDATE ),
        TOKEN( "date-time-visible",               XML_DATE_TIME_VISIBLE ),
        TOKEN( "date-value",                      XML_DATE_VALUE ),
        TOKEN( "datetime",                        XML_DATETIME ),
        TOKEN( "day",                             XML_DAY ),
@@ -848,6 +850,7 @@ namespace xmloff { namespace token {
        TOKEN( "footer-first",                    XML_FOOTER_FIRST ),
        TOKEN( "footer-left",                     XML_FOOTER_LEFT ),
        TOKEN( "footer-style",                    XML_FOOTER_STYLE ),
        TOKEN( "footer-visible",                  XML_FOOTER_VISIBLE ),
        TOKEN( "footnote",                        XML_FOOTNOTE ),
        TOKEN( "footnote-body",                   XML_FOOTNOTE_BODY ),
        TOKEN( "footnote-citation",               XML_FOOTNOTE_CITATION ),
@@ -1381,6 +1384,7 @@ namespace xmloff { namespace token {
        TOKEN( "page-master-name",                XML_PAGE_MASTER_NAME ),
        TOKEN( "page-name",                       XML_PAGE_NAME ),
        TOKEN( "page-number",                     XML_PAGE_NUMBER ),
        TOKEN( "page-number-visible",             XML_PAGE_NUMBER_VISIBLE ),
        TOKEN( "page-start-margin",               XML_PAGE_START_MARGIN ),
        TOKEN( "page-style-name",                 XML_PAGE_STYLE_NAME ),
        TOKEN( "page-thumbnail",                  XML_PAGE_THUMBNAIL ),
diff --git a/xmloff/source/meta/xmlmetai.cxx b/xmloff/source/meta/xmlmetai.cxx
index 0a39e72..459f3cf 100644
--- a/xmloff/source/meta/xmlmetai.cxx
+++ b/xmloff/source/meta/xmlmetai.cxx
@@ -162,6 +162,19 @@ SvXMLMetaDocumentContext::SvXMLMetaDocumentContext(SvXMLImport& rImport,
//    OSL_ENSURE(xDocProps.is(), "SvXMLMetaDocumentContext: no document props");
}

SvXMLMetaDocumentContext::SvXMLMetaDocumentContext(SvXMLImport& rImport,
            sal_Int32 /*nElement*/,
            const uno::Reference<document::XDocumentProperties>& xDocProps) :
    SvXMLImportContext( rImport ),
    mxDocProps(xDocProps),
    mxDocBuilder(
        xml::dom::SAXDocumentBuilder::create(
            comphelper::getProcessComponentContext()))
{
// #i103539#: must always read meta.xml for generator, xDocProps unwanted then
//    OSL_ENSURE(xDocProps.is(), "SvXMLMetaDocumentContext: no document props");
}

SvXMLMetaDocumentContext::~SvXMLMetaDocumentContext()
{
}
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index 1a1db7b..3c9d083 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -499,6 +499,8 @@ date-is
date-adjust
date-style
date-time
date-time-update
date-time-visible
date-value
datetime
day
@@ -770,6 +772,7 @@ footer
footer-first
footer-left
footer-style
footer-visible
footnote
footnote-body
footnote-citation
@@ -1298,6 +1301,7 @@ page-master
page-master-name
page-name
page-number
page-number-visible
page-start-margin
page-style-name
page-thumbnail
diff --git a/xmloff/source/transform/ChartPlotAreaOASISTContext.cxx b/xmloff/source/transform/ChartPlotAreaOASISTContext.cxx
index 18733301..ddd022e 100644
--- a/xmloff/source/transform/ChartPlotAreaOASISTContext.cxx
+++ b/xmloff/source/transform/ChartPlotAreaOASISTContext.cxx
@@ -167,11 +167,11 @@ void XMLAxisOASISContext::EndElement()
                                    XML_CATEGORY ), "Axis Dimension: invalid new value" );
        }

        GetTransformer().GetDocHandler()->startElement(
        GetTransformer().startFastElement(
            GetExportQName(),
            Reference< xml::sax::XAttributeList >( pMutableAttrList ));
        ExportContent();
        GetTransformer().GetDocHandler()->endElement( GetExportQName());
        GetTransformer().endFastElement( GetExportQName());
    }
    else
        Export();
diff --git a/xmloff/source/transform/ControlOASISTContext.cxx b/xmloff/source/transform/ControlOASISTContext.cxx
index 3b5ece6..f5940a2 100644
--- a/xmloff/source/transform/ControlOASISTContext.cxx
+++ b/xmloff/source/transform/ControlOASISTContext.cxx
@@ -135,7 +135,7 @@ void XMLControlOASISTransformerContext::StartElement(
    }

    if( m_bCreateControl )
        GetTransformer().GetDocHandler()->startElement( m_aElemQName,
        GetTransformer().startFastElement( m_aElemQName,
                                                        xControlAttrList );
    XMLTransformerContext::StartElement( xAttrList );
}
@@ -144,7 +144,7 @@ void XMLControlOASISTransformerContext::EndElement()
{
    XMLTransformerContext::EndElement();
    if( m_bCreateControl )
        GetTransformer().GetDocHandler()->endElement( m_aElemQName );
        GetTransformer().endFastElement( m_aElemQName );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/transform/ControlOOoTContext.cxx b/xmloff/source/transform/ControlOOoTContext.cxx
index b37a734..9f42d35 100644
--- a/xmloff/source/transform/ControlOOoTContext.cxx
+++ b/xmloff/source/transform/ControlOOoTContext.cxx
@@ -63,7 +63,7 @@ rtl::Reference<XMLTransformerContext> XMLControlOOoTransformerContext::CreateChi
        GetTransformer().ProcessAttrList( m_xAttrList,
                                          OOO_FORM_CONTROL_ACTIONS,
                                          false );
        GetTransformer().GetDocHandler()->startElement( m_aElemQName,
        GetTransformer().startFastElement( m_aElemQName,
                                                        m_xAttrList );
    }
    else
@@ -77,7 +77,7 @@ rtl::Reference<XMLTransformerContext> XMLControlOOoTransformerContext::CreateChi

void XMLControlOOoTransformerContext::EndElement()
{
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().endFastElement( m_aElemQName );
}

void XMLControlOOoTransformerContext::Characters( const OUString& rChars )
diff --git a/xmloff/source/transform/EventOOoTContext.cxx b/xmloff/source/transform/EventOOoTContext.cxx
index 42cc1ab..264bc12 100644
--- a/xmloff/source/transform/EventOOoTContext.cxx
+++ b/xmloff/source/transform/EventOOoTContext.cxx
@@ -209,8 +209,7 @@ void XMLEventOOoTransformerContext::StartElement(
    if( m_bPersistent )
        XMLPersElemContentTContext::StartElement( xAttrList );
    else
        GetTransformer().GetDocHandler()->startElement( GetExportQName(),
                                                        xAttrList );
        GetTransformer().startFastElement( GetExportQName(), xAttrList );
}

void XMLEventOOoTransformerContext::EndElement()
@@ -218,7 +217,7 @@ void XMLEventOOoTransformerContext::EndElement()
    if( m_bPersistent )
        XMLPersElemContentTContext::EndElement();
    else
        GetTransformer().GetDocHandler()->endElement( GetExportQName() );
        GetTransformer().endFastElement( GetExportQName() );
}

rtl::Reference<XMLTransformerContext> XMLEventOOoTransformerContext::CreateChildContext(
diff --git a/xmloff/source/transform/FormPropOASISTContext.cxx b/xmloff/source/transform/FormPropOASISTContext.cxx
index 2e68b23..ab46e81 100644
--- a/xmloff/source/transform/FormPropOASISTContext.cxx
+++ b/xmloff/source/transform/FormPropOASISTContext.cxx
@@ -196,10 +196,10 @@ void XMLFormPropOASISTransformerContext::StartElement(
        OUString aValueElemQName(
            GetTransformer().GetNamespaceMap().GetQNameByKey(
                    XML_NAMESPACE_FORM, GetXMLToken( XML_PROPERTY_VALUE ) ) );
        GetTransformer().GetDocHandler()->startElement( aValueElemQName,
        GetTransformer().startFastElement( aValueElemQName,
                                                        xAttrList );
        GetTransformer().GetDocHandler()->characters( aValue );
        GetTransformer().GetDocHandler()->endElement( aValueElemQName );
        GetTransformer().endFastElement( aValueElemQName );
    }
}

diff --git a/xmloff/source/transform/FormPropOOoTContext.cxx b/xmloff/source/transform/FormPropOOoTContext.cxx
index 61ac282..b590d06 100644
--- a/xmloff/source/transform/FormPropOOoTContext.cxx
+++ b/xmloff/source/transform/FormPropOOoTContext.cxx
@@ -243,9 +243,8 @@ void XMLFormPropOOoTransformerContext::EndElement()
                                GetXMLToken( m_eValueTypeToken ) );
    }

    GetTransformer().GetDocHandler()->startElement( m_aElemQName,
                                                    m_xAttrList );
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().startFastElement( m_aElemQName, m_xAttrList );
    GetTransformer().endFastElement( m_aElemQName );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/transform/FrameOASISTContext.cxx b/xmloff/source/transform/FrameOASISTContext.cxx
index ca5b1e9..4ed0d0a 100644
--- a/xmloff/source/transform/FrameOASISTContext.cxx
+++ b/xmloff/source/transform/FrameOASISTContext.cxx
@@ -145,8 +145,7 @@ rtl::Reference<XMLTransformerContext> XMLFrameOASISTransformerContext::CreateChi
                    GetTransformer().ProcessAttrList( m_xAttrList,
                                                      OASIS_SHAPE_ACTIONS,
                                                      false );
                    GetTransformer().GetDocHandler()->startElement( m_aElemQName,
                                                                    m_xAttrList );
                    GetTransformer().startFastElement( m_aElemQName, m_xAttrList );
                }
                else
                {
@@ -175,7 +174,7 @@ rtl::Reference<XMLTransformerContext> XMLFrameOASISTransformerContext::CreateChi
void XMLFrameOASISTransformerContext::EndElement()
{
    if( !m_bIgnoreElement )
        GetTransformer().GetDocHandler()->endElement( m_aElemQName );
        GetTransformer().endFastElement( m_aElemQName );
}

void XMLFrameOASISTransformerContext::Characters( const OUString& rChars )
diff --git a/xmloff/source/transform/FrameOOoTContext.cxx b/xmloff/source/transform/FrameOOoTContext.cxx
index 0176964..8c66584 100644
--- a/xmloff/source/transform/FrameOOoTContext.cxx
+++ b/xmloff/source/transform/FrameOOoTContext.cxx
@@ -91,7 +91,7 @@ void XMLFrameOOoTransformerContext::StartElement(
        }
    }

    GetTransformer().GetDocHandler()->startElement( m_aElemQName,
    GetTransformer().startFastElement( m_aElemQName,
                                                    xFrameAttrList );
    XMLTransformerContext::StartElement( xAttrList );
}
@@ -140,7 +140,7 @@ void XMLFrameOOoTransformerContext::EndElement()
{
    XMLTransformerContext::EndElement();
    ExportContent();
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().endFastElement( m_aElemQName );
}

void XMLFrameOOoTransformerContext::Characters( const OUString& rChars )
diff --git a/xmloff/source/transform/MetaTContext.cxx b/xmloff/source/transform/MetaTContext.cxx
index 0e4969c..e22b51d 100644
--- a/xmloff/source/transform/MetaTContext.cxx
+++ b/xmloff/source/transform/MetaTContext.cxx
@@ -101,7 +101,7 @@ void XMLMetaTransformerContext::EndElement()

                Reference< XAttributeList > xAttrList =
                    new XMLMutableAttributeList;
                GetTransformer().GetDocHandler()->startElement( aKeywordsQName,
                GetTransformer().startFastElement( aKeywordsQName,
                                                            xAttrList );
            }

@@ -115,12 +115,12 @@ void XMLMetaTransformerContext::EndElement()
            }

            if( XML_KEYWORD == *pToken )
                GetTransformer().GetDocHandler()->endElement( aKeywordsQName );
                GetTransformer().endFastElement( aKeywordsQName );
        }
        pToken++;
    }

    GetTransformer().GetDocHandler()->endElement( GetQName() );
    GetTransformer().endFastElement( GetQName() );
}

void XMLMetaTransformerContext::Characters( const OUString& )
diff --git a/xmloff/source/transform/NotesTContext.cxx b/xmloff/source/transform/NotesTContext.cxx
index bef8abc..b28115f 100644
--- a/xmloff/source/transform/NotesTContext.cxx
+++ b/xmloff/source/transform/NotesTContext.cxx
@@ -137,7 +137,7 @@ void XMLNotesTransformerContext::StartElement(
    if( m_bPersistent )
        XMLPersElemContentTContext::StartElement( xAttrList );
    else
        GetTransformer().GetDocHandler()->startElement( GetExportQName(),
        GetTransformer().startFastElement( GetExportQName(),
                                                        xAttrList );
}

@@ -149,7 +149,7 @@ void XMLNotesTransformerContext::EndElement()
    }
    else
    {
        GetTransformer().GetDocHandler()->endElement( GetExportQName() );
        GetTransformer().endFastElement( GetExportQName() );
    }
}

diff --git a/xmloff/source/transform/OOo2Oasis.cxx b/xmloff/source/transform/OOo2Oasis.cxx
index c6cc7c4..e5e188e 100644
--- a/xmloff/source/transform/OOo2Oasis.cxx
+++ b/xmloff/source/transform/OOo2Oasis.cxx
@@ -1213,12 +1213,12 @@ void XMLDocumentTransformerContext_Impl::StartElement(
                        XML_NAMESPACE_SVG ) );
    }

    GetTransformer().GetDocHandler()->startElement( m_aElemQName, xAttrList );
    GetTransformer().startFastElement( m_aElemQName, xAttrList );
}

void XMLDocumentTransformerContext_Impl::EndElement()
{
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().endFastElement( m_aElemQName );

    GetTransformer().SetClass( m_aOldClass );
}
@@ -1267,13 +1267,13 @@ void XMLBodyTransformerContext_Impl::StartElement(

    m_aClassQName = GetTransformer().GetNamespaceMap().GetQNameByKey(
                        XML_NAMESPACE_OFFICE, aClass );
    GetTransformer().GetDocHandler()->startElement( m_aClassQName,
    GetTransformer().startFastElement( m_aClassQName,
                                                    xAttrList );
}

void XMLBodyTransformerContext_Impl::EndElement()
{
    GetTransformer().GetDocHandler()->endElement( m_aClassQName );
    GetTransformer().endFastElement( m_aClassQName );
    XMLTransformerContext::EndElement();
}

@@ -1483,12 +1483,12 @@ void XMLTableOOoTransformerContext_Impl::StartElement(
        }
    }

    GetTransformer().GetDocHandler()->startElement( m_aElemQName, xAttrList );
    GetTransformer().startFastElement( m_aElemQName, xAttrList );
}

void XMLTableOOoTransformerContext_Impl::EndElement()
{
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().endFastElement( m_aElemQName );
}

XMLTransformerContext *OOo2OasisTransformer::CreateUserDefinedContext(
diff --git a/xmloff/source/transform/Oasis2OOo.cxx b/xmloff/source/transform/Oasis2OOo.cxx
index 257f199..e901264 100644
--- a/xmloff/source/transform/Oasis2OOo.cxx
+++ b/xmloff/source/transform/Oasis2OOo.cxx
@@ -1226,12 +1226,12 @@ void XMLTableTransformerContext_Impl::StartElement(
        }
    }

    GetTransformer().GetDocHandler()->startElement( m_aElemQName, xAttrList );
    GetTransformer().startFastElement( m_aElemQName, xAttrList );
}

void XMLTableTransformerContext_Impl::EndElement()
{
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().endFastElement( m_aElemQName );
}

class XMLBodyOASISTransformerContext_Impl : public XMLTransformerContext
diff --git a/xmloff/source/transform/PersAttrListTContext.cxx b/xmloff/source/transform/PersAttrListTContext.cxx
index c604a09..f021af6 100644
--- a/xmloff/source/transform/PersAttrListTContext.cxx
+++ b/xmloff/source/transform/PersAttrListTContext.cxx
@@ -161,9 +161,9 @@ bool XMLPersAttrListTContext::IsPersistent() const

void XMLPersAttrListTContext::Export()
{
    GetTransformer().GetDocHandler()->startElement( m_aElemQName, m_xAttrList );
    GetTransformer().startFastElement( m_aElemQName, m_xAttrList );
    ExportContent();
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().endFastElement( m_aElemQName );
}

void XMLPersAttrListTContext::ExportContent()
diff --git a/xmloff/source/transform/ProcAddAttrTContext.cxx b/xmloff/source/transform/ProcAddAttrTContext.cxx
index 2adf278..821ccd9 100644
--- a/xmloff/source/transform/ProcAddAttrTContext.cxx
+++ b/xmloff/source/transform/ProcAddAttrTContext.cxx
@@ -60,7 +60,7 @@ void XMLProcAddAttrTransformerContext::StartElement(
        xAttrList = pMutableAttrList;
    }
    pMutableAttrList->AddAttribute( m_aAttrQName, m_aAttrValue );
    GetTransformer().GetDocHandler()->startElement( GetElemQName(), xAttrList );
    GetTransformer().startFastElement( GetElemQName(), xAttrList );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/transform/ProcAttrTContext.cxx b/xmloff/source/transform/ProcAttrTContext.cxx
index 4f142b3..0af4e4c 100644
--- a/xmloff/source/transform/ProcAttrTContext.cxx
+++ b/xmloff/source/transform/ProcAttrTContext.cxx
@@ -56,12 +56,12 @@ void XMLProcAttrTransformerContext::StartElement(
{
    Reference< XAttributeList > xAttrList( rAttrList );
    GetTransformer().ProcessAttrList( xAttrList, m_nActionMap, false );
    GetTransformer().GetDocHandler()->startElement( m_aElemQName, xAttrList );
    GetTransformer().startFastElement( m_aElemQName, xAttrList );
}

void XMLProcAttrTransformerContext::EndElement()
{
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().endFastElement( m_aElemQName );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/transform/RenameElemTContext.cxx b/xmloff/source/transform/RenameElemTContext.cxx
index 6816d66..81ea2da 100644
--- a/xmloff/source/transform/RenameElemTContext.cxx
+++ b/xmloff/source/transform/RenameElemTContext.cxx
@@ -69,12 +69,12 @@ void XMLRenameElemTransformerContext::StartElement(
        xAttrList = pMutableAttrList;
        pMutableAttrList->AddAttribute( m_aAttrQName, m_aAttrValue );
    }
    GetTransformer().GetDocHandler()->startElement( m_aElemQName, xAttrList );
    GetTransformer().startFastElement( m_aElemQName, xAttrList );
}

void XMLRenameElemTransformerContext::EndElement()
{
    GetTransformer().GetDocHandler()->endElement( m_aElemQName );
    GetTransformer().endFastElement( m_aElemQName );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/transform/StyleOASISTContext.cxx b/xmloff/source/transform/StyleOASISTContext.cxx
index 38a3d43..6018aa5 100644
--- a/xmloff/source/transform/StyleOASISTContext.cxx
+++ b/xmloff/source/transform/StyleOASISTContext.cxx
@@ -609,10 +609,9 @@ void XMLPropertiesTContext_Impl::StartElement(

void XMLPropertiesTContext_Impl::Export()
{
    GetTransformer().GetDocHandler()->startElement( GetExportQName(),
                                                    m_xAttrList );
    GetTransformer().startFastElement( GetExportQName(), m_xAttrList );
    ExportContent();
    GetTransformer().GetDocHandler()->endElement( GetExportQName() );
    GetTransformer().endFastElement( GetExportQName() );
}

XMLPropType XMLPropertiesTContext_Impl::GetPropType( const OUString& rLocalName )
@@ -896,8 +895,7 @@ void XMLStyleOASISTContext::StartElement(
    if( m_bPersistent )
        XMLPersElemContentTContext::StartElement( xAttrList );
    else
        GetTransformer().GetDocHandler()->startElement( GetExportQName(),
                                                        xAttrList );
        GetTransformer().startFastElement( GetExportQName(), xAttrList );
}

void XMLStyleOASISTContext::EndElement()
@@ -914,7 +912,7 @@ void XMLStyleOASISTContext::EndElement()
            m_xPropContext->Export();
            m_xPropContext = nullptr;
        }
        GetTransformer().GetDocHandler()->endElement( GetExportQName() );
        GetTransformer().endFastElement( GetExportQName() );
    }
}

diff --git a/xmloff/source/transform/StyleOOoTContext.cxx b/xmloff/source/transform/StyleOOoTContext.cxx
index bf841ca4..077e7b0 100644
--- a/xmloff/source/transform/StyleOOoTContext.cxx
+++ b/xmloff/source/transform/StyleOOoTContext.cxx
@@ -197,9 +197,9 @@ void XMLTypedPropertiesOOoTContext_Impl::Export()
{
    if( m_xAttrList->getLength() || HasElementContent() )
    {
        GetTransformer().GetDocHandler()->startElement( GetQName(), m_xAttrList );
        GetTransformer().startFastElement( GetQName(), m_xAttrList );
        ExportContent();
        GetTransformer().GetDocHandler()->endElement( GetQName() );
        GetTransformer().endFastElement( GetQName() );
    }
}

@@ -1254,8 +1254,7 @@ void XMLStyleOOoTContext::StartElement(
    if( m_bPersistent )
        XMLPersElemContentTContext::StartElement( xAttrList );
    else
        GetTransformer().GetDocHandler()->startElement( GetExportQName(),
                                                        xAttrList );
        GetTransformer().startFastElement( GetExportQName(), xAttrList );
}

void XMLStyleOOoTContext::EndElement()
@@ -1263,7 +1262,7 @@ void XMLStyleOOoTContext::EndElement()
    if( m_bPersistent )
        XMLPersElemContentTContext::EndElement();
    else
        GetTransformer().GetDocHandler()->endElement( GetExportQName() );
        GetTransformer().endFastElement( GetExportQName() );
}

void XMLStyleOOoTContext::Characters( const OUString& )
diff --git a/xmloff/source/transform/TransformerBase.cxx b/xmloff/source/transform/TransformerBase.cxx
index f5770726..08c4a21 100644
--- a/xmloff/source/transform/TransformerBase.cxx
+++ b/xmloff/source/transform/TransformerBase.cxx
@@ -40,6 +40,7 @@
#include "TransformerTokenMap.hxx"

#include "TransformerBase.hxx"
#include <xmloff/xmlimp.hxx>

using namespace ::osl;
using namespace ::xmloff::token;
@@ -184,10 +185,13 @@ XMLTransformerActions *XMLTransformerBase::GetUserDefinedActions( sal_uInt16 )
XMLTransformerBase::XMLTransformerBase( XMLTransformerActionInit *pInit,
                                    ::xmloff::token::XMLTokenEnum *pTKMapInit )
    throw () :
    m_xTokenHandler( new FastTokenHandler() ),
    m_pNamespaceMap( new SvXMLNamespaceMap ),
    m_pReplaceNamespaceMap( new SvXMLNamespaceMap ),
    m_pElemActions( new XMLTransformerActions( pInit ) ),
    m_pTokenMap( new XMLTransformerTokenMap( pTKMapInit ) )
    m_pTokenMap( new XMLTransformerTokenMap( pTKMapInit ) ),
    m_xFastAttributes( new sax_fastparser::FastAttributeList( m_xTokenHandler.get(),
        dynamic_cast< sax_fastparser::FastTokenHandlerBase *>( m_xTokenHandler.get() ) ) )
{
    GetNamespaceMap().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
    GetNamespaceMap().Add( GetXMLToken(XML_NP_DC), GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
@@ -429,7 +433,12 @@ void SAL_CALL XMLTransformerBase::initialize( const Sequence< Any >& aArguments 

        // document handler
        if( cppu::UnoType<XDocumentHandler>::get().isAssignableFrom( pAny->getValueType() ) )
        {
            m_xHandler.set( *pAny, UNO_QUERY );
            m_xFastHandler.set( m_xHandler.get(), UNO_QUERY );
            if ( (dynamic_cast< SvXMLImport* >( m_xFastHandler.get() ) ) )
                m_xNamespaceHandler = (dynamic_cast< SvXMLImport* >( m_xFastHandler.get() ) )->getNamespaceHandler();
        }

        // property set to transport data across
        if( cppu::UnoType<XPropertySet>::get().isAssignableFrom( pAny->getValueType() ) )
@@ -1455,4 +1464,50 @@ bool XMLTransformerBase::isWriter() const
            xSI->supportsService("com.sun.star.text.GlobalDocument") );
}

void XMLTransformerBase::startFastElement( const OUString& rName,
                                         const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
    if( m_xFastHandler.is() )
    {
        OUString aLocalName;
        sal_uInt16 nPrefix = m_pNamespaceMap->GetKeyByAttrName( rName, &aLocalName );
        nElement = NAMESPACE_TOKEN( nPrefix ) | m_xTokenHandler->getTokenDirect(
                        OUStringToOString( aLocalName, RTL_TEXTENCODING_ASCII_US ).getStr(), aLocalName.getLength() ) ;
        m_xFastAttributes->clear();

        sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
        for( sal_Int16 i=0; i < nAttrCount; i++ )
        {
            OUString aLocalAttrName;
            const OUString& rAttrName = xAttrList->getNameByIndex( i );
            const OUString& rAttrValue = xAttrList->getValueByIndex( i );
            sal_uInt16 nAttrPrefix = m_pNamespaceMap->GetKeyByAttrName( rAttrName, &aLocalAttrName );
            if( XML_NAMESPACE_XMLNS == nAttrPrefix )
            {
                if ( m_xNamespaceHandler.is() )
                    m_xNamespaceHandler->registerNamespace( aLocalAttrName, rAttrValue );
            }
            else
            {
                sal_Int32 nAttr = NAMESPACE_TOKEN( nAttrPrefix ) | m_xTokenHandler->getTokenDirect(
                                    OUStringToOString( aLocalAttrName, RTL_TEXTENCODING_ASCII_US ).getStr(), aLocalAttrName.getLength() ) ;
                m_xFastAttributes->add( nAttr, OUStringToOString( rAttrValue, RTL_TEXTENCODING_ASCII_US ).getStr() );
            }
        }
        m_xFastHandler->startFastElement( nElement, m_xFastAttributes.get() );
    }
    else
        m_xHandler->startElement( rName, xAttrList );
}

void XMLTransformerBase::endFastElement( const OUString& rName )
{
    if( m_xFastHandler.is() )
       m_xFastHandler->endFastElement( nElement );
    else
        m_xHandler->endElement( rName );
}



/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/transform/TransformerBase.hxx b/xmloff/source/transform/TransformerBase.hxx
index a22fa73..2dbb32a 100644
--- a/xmloff/source/transform/TransformerBase.hxx
+++ b/xmloff/source/transform/TransformerBase.hxx
@@ -27,13 +27,17 @@
#include <com/sun/star/xml/sax/SAXParseException.hpp>
#include <com/sun/star/xml/sax/SAXException.hpp>
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
#include <com/sun/star/xml/sax/XFastNamespaceHandler.hpp>
#include <com/sun/star/xml/sax/XLocator.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <rtl/ref.hxx>
#include <xmloff/xmltoken.hxx>
#include <sax/fastattribs.hxx>

#include "Transformer.hxx"
#include <xmloff/fasttokenhandler.hxx>

namespace com { namespace sun { namespace star {
    namespace i18n { class XCharacterClassification; }
@@ -56,8 +60,11 @@ class XMLTransformerBase : public XMLTransformer
    css::uno::Reference< css::xml::sax::XLocator >                    m_xLocator;
    css::uno::Reference< css::xml::sax::XDocumentHandler >            m_xHandler;     // the handlers
    css::uno::Reference< css::xml::sax::XExtendedDocumentHandler >    m_xExtHandler;
    css::uno::Reference< css::xml::sax::XFastDocumentHandler >        m_xFastHandler;
    css::uno::Reference< css::beans::XPropertySet >                   m_xPropSet;
    css::uno::Reference< css::i18n::XCharacterClassification >        xCharClass;
    rtl::Reference< xmloff::token::FastTokenHandler >                 m_xTokenHandler;
    css::uno::Reference< css::xml::sax::XFastNamespaceHandler >       m_xNamespaceHandler;

    OUString m_aExtPathPrefix;
    OUString m_aClass;
@@ -68,6 +75,10 @@ class XMLTransformerBase : public XMLTransformer
    XMLTransformerActions       *m_pElemActions;
    XMLTransformerTokenMap      *m_pTokenMap;

    //for feeding FastDocumentHandler
    sal_Int32 nElement;
    rtl::Reference< sax_fastparser::FastAttributeList > m_xFastAttributes;

protected:
    css::uno::Reference< css::frame::XModel >     mxModel;

@@ -187,6 +198,10 @@ public:

    bool isWriter() const;

    void startFastElement( const OUString& rName,
                                         const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList );
    void endFastElement( const OUString& rName );

};

#endif // INCLUDED_XMLOFF_SOURCE_TRANSFORM_TRANSFORMERBASE_HXX
diff --git a/xmloff/source/transform/TransformerContext.cxx b/xmloff/source/transform/TransformerContext.cxx
index 7181c2a..5ff0d94 100644
--- a/xmloff/source/transform/TransformerContext.cxx
+++ b/xmloff/source/transform/TransformerContext.cxx
@@ -62,12 +62,12 @@ rtl::Reference<XMLTransformerContext> XMLTransformerContext::CreateChildContext(

void XMLTransformerContext::StartElement( const Reference< XAttributeList >& rAttrList )
{
    m_rTransformer.GetDocHandler()->startElement( m_aQName, rAttrList );
    m_rTransformer.startFastElement( m_aQName, rAttrList );
}

void XMLTransformerContext::EndElement()
{
    m_rTransformer.GetDocHandler()->endElement( m_aQName );
    GetTransformer().endFastElement( m_aQName );
}

void XMLTransformerContext::Characters( const OUString& rChars )