diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2012-11-19 16:45:55 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2012-11-28 13:28:31 -0500 |
commit | 1157cbc99391c121bbe5e75291ce7a2cc75f5eba (patch) | |
tree | 1d4cff9f336690469d36e214a79ded44ffb9541b /sc/source/filter | |
parent | 83c2f4c830559ce3aa0b448a604c93882af4f231 (diff) |
Separate the XML part of orcus filters into own class.
Along with other reorganization of the orcus interface code...
This XML context object will be used to store data specific to each
loaded XML file, such as XML stream, namespace repository and so on.
Change-Id: I21c43ab0026954c5d52f4985a169934f8fb9f704
Diffstat (limited to 'sc/source/filter')
-rw-r--r-- | sc/source/filter/inc/orcusfiltersimpl.hxx | 19 | ||||
-rw-r--r-- | sc/source/filter/inc/orcusinterface.hxx | 63 | ||||
-rw-r--r-- | sc/source/filter/orcus/interface.cxx | 121 | ||||
-rw-r--r-- | sc/source/filter/orcus/orcusfiltersimpl.cxx | 359 | ||||
-rw-r--r-- | sc/source/filter/orcus/xmlcontext.cxx | 221 |
5 files changed, 424 insertions, 359 deletions
diff --git a/sc/source/filter/inc/orcusfiltersimpl.hxx b/sc/source/filter/inc/orcusfiltersimpl.hxx index f2d270355293..0b6ffa6997b3 100644 --- a/sc/source/filter/inc/orcusfiltersimpl.hxx +++ b/sc/source/filter/inc/orcusfiltersimpl.hxx @@ -15,13 +15,24 @@ class ScOrcusFiltersImpl : public ScOrcusFilters { public: + static rtl::OString toSystemPath(const rtl::OUString& rPath); + virtual bool importCSV(ScDocument& rDoc, const rtl::OUString& rPath) const; - virtual bool loadXMLStructure( - const rtl::OUString& rPath, SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const; + virtual ScOrcusXMLContext* createXMLContext(ScDocument& rDoc, const rtl::OUString& rPath) const; +}; + +class ScOrcusXMLContextImpl : public ScOrcusXMLContext +{ + ScDocument& mrDoc; + rtl::OUString maPath; +public: + ScOrcusXMLContextImpl(ScDocument& rDoc, const rtl::OUString& rPath); + virtual ~ScOrcusXMLContextImpl(); + + virtual bool loadXMLStructure(SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const; - virtual bool importXML( - ScDocument& rDoc, const rtl::OUString& rPath, const ScOrcusImportXMLParam& rParam) const; + virtual bool importXML(const ScOrcusImportXMLParam& rParam) const; }; #endif diff --git a/sc/source/filter/inc/orcusinterface.hxx b/sc/source/filter/inc/orcusinterface.hxx new file mode 100644 index 000000000000..e2c9c087f6fa --- /dev/null +++ b/sc/source/filter/inc/orcusinterface.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef __SC_ORCUSINTERFACE_HXX__ +#define __SC_ORCUSINTERFACE_HXX__ + +#include "address.hxx" + +#define __ORCUS_STATIC_LIB +#include <orcus/spreadsheet/import_interface.hpp> + +#include <boost/ptr_container/ptr_vector.hpp> + +class ScDocument; +class ScOrcusSheet; + +class ScOrcusFactory : public orcus::spreadsheet::iface::import_factory +{ + ScDocument& mrDoc; + boost::ptr_vector<ScOrcusSheet> maSheets; + +public: + ScOrcusFactory(ScDocument& rDoc); + + virtual orcus::spreadsheet::iface::import_sheet* append_sheet(const char *sheet_name, size_t sheet_name_length); + virtual orcus::spreadsheet::iface::import_sheet* get_sheet(const char *sheet_name, size_t sheet_name_length); + virtual orcus::spreadsheet::iface::import_shared_strings* get_shared_strings(); + virtual orcus::spreadsheet::iface::import_styles* get_styles(); +}; + +class ScOrcusSheet : public orcus::spreadsheet::iface::import_sheet +{ + ScDocument& mrDoc; + SCTAB mnTab; +public: + ScOrcusSheet(ScDocument& rDoc, SCTAB nTab); + + // Orcus import interface + virtual void set_auto(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, const char* p, size_t n); + virtual void set_format(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, size_t xf_index); + virtual void set_formula(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, orcus::spreadsheet::formula_grammar_t grammar, const char* p, size_t n); + virtual void set_formula_result(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, const char* p, size_t n); + virtual void set_shared_formula( + orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, orcus::spreadsheet::formula_grammar_t grammar, size_t sindex, + const char* p_formula, size_t n_formula); + virtual void set_shared_formula( + orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, orcus::spreadsheet::formula_grammar_t grammar, size_t sindex, + const char* p_formula, size_t n_formula, const char* p_range, size_t n_range); + virtual void set_shared_formula(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, size_t sindex); + virtual void set_string(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, size_t sindex); + virtual void set_value(orcus::spreadsheet::row_t row, orcus::spreadsheet::col_t col, double value); + + SCTAB getIndex() const { return mnTab; } +}; + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx new file mode 100644 index 000000000000..d22c20844d36 --- /dev/null +++ b/sc/source/filter/orcus/interface.cxx @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcusinterface.hxx" + +#include "document.hxx" + +using orcus::spreadsheet::row_t; +using orcus::spreadsheet::col_t; +using orcus::spreadsheet::formula_grammar_t; + +ScOrcusFactory::ScOrcusFactory(ScDocument& rDoc) : mrDoc(rDoc) {} + +orcus::spreadsheet::iface::import_sheet* ScOrcusFactory::append_sheet(const char* sheet_name, size_t sheet_name_length) +{ + OUString aTabName(sheet_name, sheet_name_length, RTL_TEXTENCODING_UTF8); + if (!mrDoc.InsertTab(SC_TAB_APPEND, aTabName)) + return NULL; + + SCTAB nTab = mrDoc.GetTableCount() - 1; + maSheets.push_back(new ScOrcusSheet(mrDoc, nTab)); + return &maSheets.back(); +} + +class FindSheetByIndex : std::unary_function<ScOrcusSheet, bool> +{ + SCTAB mnTab; +public: + FindSheetByIndex(SCTAB nTab) : mnTab(nTab) {} + bool operator() (const ScOrcusSheet& rSheet) const + { + return rSheet.getIndex() == mnTab; + } +}; + +orcus::spreadsheet::iface::import_sheet* ScOrcusFactory::get_sheet(const char* sheet_name, size_t sheet_name_length) +{ + OUString aTabName(sheet_name, sheet_name_length, RTL_TEXTENCODING_UTF8); + SCTAB nTab = -1; + if (!mrDoc.GetTable(aTabName, nTab)) + // Sheet by that name not found. + return NULL; + + // See if we already have an orcus sheet instance by that index. + boost::ptr_vector<ScOrcusSheet>::iterator it = + std::find_if(maSheets.begin(), maSheets.end(), FindSheetByIndex(nTab)); + + if (it != maSheets.end()) + // We already have one. Return it. + return &(*it); + + // Create a new orcus sheet instance for this. + maSheets.push_back(new ScOrcusSheet(mrDoc, nTab)); + return &maSheets.back(); +} + +orcus::spreadsheet::iface::import_shared_strings* ScOrcusFactory::get_shared_strings() +{ + // We don't support it yet. + return NULL; +} + +orcus::spreadsheet::iface::import_styles* ScOrcusFactory::get_styles() +{ + // We don't support it yet. + return NULL; +} + +ScOrcusSheet::ScOrcusSheet(ScDocument& rDoc, SCTAB nTab) : + mrDoc(rDoc), mnTab(nTab) {} + +void ScOrcusSheet::set_auto(row_t row, col_t col, const char* p, size_t n) +{ + OUString aVal(p, n, RTL_TEXTENCODING_UTF8); + mrDoc.SetString(col, row, mnTab, aVal); +} + +void ScOrcusSheet::set_format(row_t /*row*/, col_t /*col*/, size_t /*xf_index*/) +{ +} + +void ScOrcusSheet::set_formula( + row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, const char* /*p*/, size_t /*n*/) +{ +} + +void ScOrcusSheet::set_formula_result(row_t /*row*/, col_t /*col*/, const char* /*p*/, size_t /*n*/) +{ +} + +void ScOrcusSheet::set_shared_formula( + row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, size_t /*sindex*/, + const char* /*p_formula*/, size_t /*n_formula*/) +{ +} + +void ScOrcusSheet::set_shared_formula( + row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, size_t /*sindex*/, + const char* /*p_formula*/, size_t /*n_formula*/, const char* /*p_range*/, size_t /*n_range*/) +{ +} + +void ScOrcusSheet::set_shared_formula(row_t /*row*/, col_t /*col*/, size_t /*sindex*/) +{ +} + +void ScOrcusSheet::set_string(row_t /*row*/, col_t /*col*/, size_t /*sindex*/) +{ +} + +void ScOrcusSheet::set_value(row_t /*row*/, col_t /*col*/, double /*value*/) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/orcus/orcusfiltersimpl.cxx b/sc/source/filter/orcus/orcusfiltersimpl.cxx index 3fa23e14f5f3..0f1c32984175 100644 --- a/sc/source/filter/orcus/orcusfiltersimpl.cxx +++ b/sc/source/filter/orcus/orcusfiltersimpl.cxx @@ -8,187 +8,29 @@ */ #include "orcusfiltersimpl.hxx" +#include "orcusinterface.hxx" #include "document.hxx" -#include "orcusxml.hxx" #include "tools/urlobj.hxx" -#include "svtools/treelistbox.hxx" #define __ORCUS_STATIC_LIB #include <orcus/spreadsheet/import_interface.hpp> #include <orcus/orcus_csv.hpp> -#include <orcus/xml_structure_tree.hpp> -#include <orcus/xml_namespace.hpp> -#include <orcus/orcus_xml.hpp> #include <orcus/global.hpp> -#include <boost/ptr_container/ptr_vector.hpp> - -using orcus::spreadsheet::row_t; -using orcus::spreadsheet::col_t; -using orcus::spreadsheet::formula_grammar_t; - #ifdef WNT #define SYSTEM_PATH INetURLObject::FSYS_DOS #else #define SYSTEM_PATH INetURLObject::FSYS_UNX #endif -namespace { - -OString toSystemPath(const OUString& rPath) +OString ScOrcusFiltersImpl::toSystemPath(const OUString& rPath) { INetURLObject aURL(rPath); return rtl::OUStringToOString(aURL.getFSysPath(SYSTEM_PATH), RTL_TEXTENCODING_UTF8); } -class ScOrcusSheet; - -class ScOrcusFactory : public orcus::spreadsheet::iface::import_factory -{ - ScDocument& mrDoc; - boost::ptr_vector<ScOrcusSheet> maSheets; - -public: - ScOrcusFactory(ScDocument& rDoc); - - virtual orcus::spreadsheet::iface::import_sheet* append_sheet(const char *sheet_name, size_t sheet_name_length); - virtual orcus::spreadsheet::iface::import_sheet* get_sheet(const char *sheet_name, size_t sheet_name_length); - virtual orcus::spreadsheet::iface::import_shared_strings* get_shared_strings(); - virtual orcus::spreadsheet::iface::import_styles* get_styles(); -}; - -class ScOrcusSheet : public orcus::spreadsheet::iface::import_sheet -{ - ScDocument& mrDoc; - SCTAB mnTab; -public: - ScOrcusSheet(ScDocument& rDoc, SCTAB nTab); - - // Orcus import interface - virtual void set_auto(row_t row, col_t col, const char* p, size_t n); - virtual void set_format(row_t row, col_t col, size_t xf_index); - virtual void set_formula(row_t row, col_t col, formula_grammar_t grammar, const char* p, size_t n); - virtual void set_formula_result(row_t row, col_t col, const char* p, size_t n); - virtual void set_shared_formula( - row_t row, col_t col, formula_grammar_t grammar, size_t sindex, - const char* p_formula, size_t n_formula); - virtual void set_shared_formula( - row_t row, col_t col, formula_grammar_t grammar, size_t sindex, - const char* p_formula, size_t n_formula, const char* p_range, size_t n_range); - virtual void set_shared_formula(row_t row, col_t col, size_t sindex); - virtual void set_string(row_t row, col_t col, size_t sindex); - virtual void set_value(row_t row, col_t col, double value); - - SCTAB getIndex() const { return mnTab; } -}; - -ScOrcusFactory::ScOrcusFactory(ScDocument& rDoc) : mrDoc(rDoc) {} - -orcus::spreadsheet::iface::import_sheet* ScOrcusFactory::append_sheet(const char* sheet_name, size_t sheet_name_length) -{ - OUString aTabName(sheet_name, sheet_name_length, RTL_TEXTENCODING_UTF8); - if (!mrDoc.InsertTab(SC_TAB_APPEND, aTabName)) - return NULL; - - SCTAB nTab = mrDoc.GetTableCount() - 1; - maSheets.push_back(new ScOrcusSheet(mrDoc, nTab)); - return &maSheets.back(); -} - -class FindSheetByIndex : std::unary_function<ScOrcusSheet, bool> -{ - SCTAB mnTab; -public: - FindSheetByIndex(SCTAB nTab) : mnTab(nTab) {} - bool operator() (const ScOrcusSheet& rSheet) const - { - return rSheet.getIndex() == mnTab; - } -}; - -orcus::spreadsheet::iface::import_sheet* ScOrcusFactory::get_sheet(const char* sheet_name, size_t sheet_name_length) -{ - OUString aTabName(sheet_name, sheet_name_length, RTL_TEXTENCODING_UTF8); - SCTAB nTab = -1; - if (!mrDoc.GetTable(aTabName, nTab)) - // Sheet by that name not found. - return NULL; - - // See if we already have an orcus sheet instance by that index. - boost::ptr_vector<ScOrcusSheet>::iterator it = - std::find_if(maSheets.begin(), maSheets.end(), FindSheetByIndex(nTab)); - - if (it != maSheets.end()) - // We already have one. Return it. - return &(*it); - - // Create a new orcus sheet instance for this. - maSheets.push_back(new ScOrcusSheet(mrDoc, nTab)); - return &maSheets.back(); -} - -orcus::spreadsheet::iface::import_shared_strings* ScOrcusFactory::get_shared_strings() -{ - // We don't support it yet. - return NULL; -} - -orcus::spreadsheet::iface::import_styles* ScOrcusFactory::get_styles() -{ - // We don't support it yet. - return NULL; -} - -ScOrcusSheet::ScOrcusSheet(ScDocument& rDoc, SCTAB nTab) : - mrDoc(rDoc), mnTab(nTab) {} - -void ScOrcusSheet::set_auto(row_t row, col_t col, const char* p, size_t n) -{ - OUString aVal(p, n, RTL_TEXTENCODING_UTF8); - mrDoc.SetString(col, row, mnTab, aVal); -} - -void ScOrcusSheet::set_format(row_t /*row*/, col_t /*col*/, size_t /*xf_index*/) -{ -} - -void ScOrcusSheet::set_formula( - row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, const char* /*p*/, size_t /*n*/) -{ -} - -void ScOrcusSheet::set_formula_result(row_t /*row*/, col_t /*col*/, const char* /*p*/, size_t /*n*/) -{ -} - -void ScOrcusSheet::set_shared_formula( - row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, size_t /*sindex*/, - const char* /*p_formula*/, size_t /*n_formula*/) -{ -} - -void ScOrcusSheet::set_shared_formula( - row_t /*row*/, col_t /*col*/, formula_grammar_t /*grammar*/, size_t /*sindex*/, - const char* /*p_formula*/, size_t /*n_formula*/, const char* /*p_range*/, size_t /*n_range*/) -{ -} - -void ScOrcusSheet::set_shared_formula(row_t /*row*/, col_t /*col*/, size_t /*sindex*/) -{ -} - -void ScOrcusSheet::set_string(row_t /*row*/, col_t /*col*/, size_t /*sindex*/) -{ -} - -void ScOrcusSheet::set_value(row_t /*row*/, col_t /*col*/, double /*value*/) -{ -} - -} // anonymous namespace - bool ScOrcusFiltersImpl::importCSV(ScDocument& rDoc, const OUString& rPath) const { ScOrcusFactory aFactory(rDoc); @@ -209,202 +51,9 @@ bool ScOrcusFiltersImpl::importCSV(ScDocument& rDoc, const OUString& rPath) cons return true; } -namespace { - -ScOrcusXMLTreeParam::EntryData& setUserDataToEntry( - SvTreeListEntry& rEntry, ScOrcusXMLTreeParam::UserDataStoreType& rStore, ScOrcusXMLTreeParam::EntryType eType) -{ - rStore.push_back(new ScOrcusXMLTreeParam::EntryData(eType)); - rEntry.SetUserData(&rStore.back()); - return rStore.back(); -} - -void populateTree( - SvTreeListBox& rTreeCtrl, orcus::xml_structure_tree::walker& rWalker, - const orcus::xml_structure_tree::entity_name& rElemName, bool bRepeat, - SvTreeListEntry* pParent, ScOrcusXMLTreeParam& rParam) -{ - OUString aName(rElemName.name.get(), rElemName.name.size(), RTL_TEXTENCODING_UTF8); - SvTreeListEntry* pEntry = rTreeCtrl.InsertEntry(aName, pParent); - if (!pEntry) - // Can this ever happen!? - return; - - ScOrcusXMLTreeParam::EntryData& rEntryData = setUserDataToEntry( - *pEntry, rParam.maUserDataStore, - bRepeat ? ScOrcusXMLTreeParam::ElementRepeat : ScOrcusXMLTreeParam::ElementDefault); - - if (bRepeat) - { - // Recurring elements use different icon. - rTreeCtrl.SetExpandedEntryBmp(pEntry, rParam.maImgElementRepeat); - rTreeCtrl.SetCollapsedEntryBmp(pEntry, rParam.maImgElementRepeat); - } - - if (pParent) - rTreeCtrl.Expand(pParent); - - orcus::xml_structure_tree::entity_names_type aNames; - - // Insert attributes. - rWalker.get_attributes(aNames); - orcus::xml_structure_tree::entity_names_type::const_iterator it = aNames.begin(); - orcus::xml_structure_tree::entity_names_type::const_iterator itEnd = aNames.end(); - for (; it != itEnd; ++it) - { - orcus::xml_structure_tree::entity_name aAttrName = *it; - SvTreeListEntry* pAttr = rTreeCtrl.InsertEntry( - OUString(aAttrName.name.get(), aAttrName.name.size(), RTL_TEXTENCODING_UTF8), pEntry); - - if (!pAttr) - continue; - - setUserDataToEntry(*pAttr, rParam.maUserDataStore, ScOrcusXMLTreeParam::Attribute); - rTreeCtrl.SetExpandedEntryBmp(pAttr, rParam.maImgAttribute); - rTreeCtrl.SetCollapsedEntryBmp(pAttr, rParam.maImgAttribute); - } - rTreeCtrl.Expand(pEntry); - - rWalker.get_children(aNames); - - // Non-leaf if it has child elements, leaf otherwise. - rEntryData.mbLeafNode = aNames.empty(); - - // Insert child elements recursively. - for (it = aNames.begin(), itEnd = aNames.end(); it != itEnd; ++it) - { - orcus::xml_structure_tree::element aElem = rWalker.descend(*it); - populateTree(rTreeCtrl, rWalker, *it, aElem.repeat, pEntry, rParam); - rWalker.ascend(); - } -} - -class TreeUpdateSwitch -{ - SvTreeListBox& mrTreeCtrl; -public: - TreeUpdateSwitch(SvTreeListBox& rTreeCtrl) : mrTreeCtrl(rTreeCtrl) - { - mrTreeCtrl.SetUpdateMode(false); - } - - ~TreeUpdateSwitch() - { - mrTreeCtrl.SetUpdateMode(true); - } -}; - -} - -bool ScOrcusFiltersImpl::loadXMLStructure( - const rtl::OUString& rPath, SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const -{ - rParam.maUserDataStore.clear(); - - OString aSysPath = toSystemPath(rPath); - const char* path = aSysPath.getStr(); - - // TODO: Use our own stream loading call instead of one from orcus. - std::string aStrm; - orcus::load_file_content(path, aStrm); - - if (aStrm.empty()) - return false; - - orcus::xmlns_repository repo; // xml namespace repository. - orcus::xmlns_context cxt = repo.create_context(); - orcus::xml_structure_tree aXmlTree(cxt); - try - { - aXmlTree.parse(&aStrm[0], aStrm.size()); - - TreeUpdateSwitch aSwitch(rTreeCtrl); - rTreeCtrl.Clear(); - rTreeCtrl.SetDefaultCollapsedEntryBmp(rParam.maImgElementDefault); - rTreeCtrl.SetDefaultExpandedEntryBmp(rParam.maImgElementDefault); - - orcus::xml_structure_tree::walker aWalker = aXmlTree.get_walker(); - - // Root element. - orcus::xml_structure_tree::element aElem = aWalker.root(); - populateTree(rTreeCtrl, aWalker, aElem.name, aElem.repeat, NULL, rParam); - } - catch (const std::exception&) - { - // Parsing of this XML file failed. - return false; - } - - return true; -} - -namespace { - -class InsertFieldPath : std::unary_function<OString, void> -{ - orcus::orcus_xml& mrFilter; -public: - InsertFieldPath(orcus::orcus_xml& rFilter) : mrFilter(rFilter) {} - void operator() (const OString& rPath) - { - mrFilter.append_field_link(rPath.getStr()); - } -}; - -} - -bool ScOrcusFiltersImpl::importXML( - ScDocument& rDoc, const rtl::OUString& rPath, const ScOrcusImportXMLParam& rParam) const +ScOrcusXMLContext* ScOrcusFiltersImpl::createXMLContext(ScDocument& rDoc, const rtl::OUString& rPath) const { - ScOrcusFactory aFactory(rDoc); - OString aSysPath = toSystemPath(rPath); - const char* path = aSysPath.getStr(); - try - { - orcus::orcus_xml filter(&aFactory, NULL); - - // Set cell links. - { - ScOrcusImportXMLParam::CellLinksType::const_iterator it = rParam.maCellLinks.begin(); - ScOrcusImportXMLParam::CellLinksType::const_iterator itEnd = rParam.maCellLinks.end(); - for (; it != itEnd; ++it) - { - const ScOrcusImportXMLParam::CellLink& rLink = *it; - OUString aTabName; - rDoc.GetName(rLink.maPos.Tab(), aTabName); - filter.set_cell_link( - rLink.maPath.getStr(), - rtl::OUStringToOString(aTabName, RTL_TEXTENCODING_UTF8).getStr(), - rLink.maPos.Row(), rLink.maPos.Col()); - } - } - - // Set range links. - { - ScOrcusImportXMLParam::RangeLinksType::const_iterator it = rParam.maRangeLinks.begin(); - ScOrcusImportXMLParam::RangeLinksType::const_iterator itEnd = rParam.maRangeLinks.end(); - for (; it != itEnd; ++it) - { - const ScOrcusImportXMLParam::RangeLink& rLink = *it; - OUString aTabName; - rDoc.GetName(rLink.maPos.Tab(), aTabName); - filter.start_range( - rtl::OUStringToOString(aTabName, RTL_TEXTENCODING_UTF8).getStr(), - rLink.maPos.Row(), rLink.maPos.Col()); - - std::for_each(rLink.maFieldPaths.begin(), rLink.maFieldPaths.end(), InsertFieldPath(filter)); - - filter.commit_range(); - } - } - - filter.read_file(path); - } - catch (const std::exception&) - { - return false; - } - return true; + return new ScOrcusXMLContextImpl(rDoc, rPath); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/orcus/xmlcontext.cxx b/sc/source/filter/orcus/xmlcontext.cxx new file mode 100644 index 000000000000..d32a55c2882c --- /dev/null +++ b/sc/source/filter/orcus/xmlcontext.cxx @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcusfiltersimpl.hxx" +#include "orcusinterface.hxx" +#include "orcusxml.hxx" +#include "document.hxx" + +#include "svtools/treelistbox.hxx" + +#define __ORCUS_STATIC_LIB +#include <orcus/spreadsheet/import_interface.hpp> +#include <orcus/xml_structure_tree.hpp> +#include <orcus/xml_namespace.hpp> +#include <orcus/orcus_xml.hpp> +#include <orcus/global.hpp> + +namespace { + +ScOrcusXMLTreeParam::EntryData& setUserDataToEntry( + SvTreeListEntry& rEntry, ScOrcusXMLTreeParam::UserDataStoreType& rStore, ScOrcusXMLTreeParam::EntryType eType) +{ + rStore.push_back(new ScOrcusXMLTreeParam::EntryData(eType)); + rEntry.SetUserData(&rStore.back()); + return rStore.back(); +} + +void populateTree( + SvTreeListBox& rTreeCtrl, orcus::xml_structure_tree::walker& rWalker, + const orcus::xml_structure_tree::entity_name& rElemName, bool bRepeat, + SvTreeListEntry* pParent, ScOrcusXMLTreeParam& rParam) +{ + OUString aName(rElemName.name.get(), rElemName.name.size(), RTL_TEXTENCODING_UTF8); + SvTreeListEntry* pEntry = rTreeCtrl.InsertEntry(aName, pParent); + if (!pEntry) + // Can this ever happen!? + return; + + ScOrcusXMLTreeParam::EntryData& rEntryData = setUserDataToEntry( + *pEntry, rParam.maUserDataStore, + bRepeat ? ScOrcusXMLTreeParam::ElementRepeat : ScOrcusXMLTreeParam::ElementDefault); + + if (bRepeat) + { + // Recurring elements use different icon. + rTreeCtrl.SetExpandedEntryBmp(pEntry, rParam.maImgElementRepeat); + rTreeCtrl.SetCollapsedEntryBmp(pEntry, rParam.maImgElementRepeat); + } + + if (pParent) + rTreeCtrl.Expand(pParent); + + orcus::xml_structure_tree::entity_names_type aNames; + + // Insert attributes. + rWalker.get_attributes(aNames); + orcus::xml_structure_tree::entity_names_type::const_iterator it = aNames.begin(); + orcus::xml_structure_tree::entity_names_type::const_iterator itEnd = aNames.end(); + for (; it != itEnd; ++it) + { + orcus::xml_structure_tree::entity_name aAttrName = *it; + SvTreeListEntry* pAttr = rTreeCtrl.InsertEntry( + OUString(aAttrName.name.get(), aAttrName.name.size(), RTL_TEXTENCODING_UTF8), pEntry); + + if (!pAttr) + continue; + + setUserDataToEntry(*pAttr, rParam.maUserDataStore, ScOrcusXMLTreeParam::Attribute); + rTreeCtrl.SetExpandedEntryBmp(pAttr, rParam.maImgAttribute); + rTreeCtrl.SetCollapsedEntryBmp(pAttr, rParam.maImgAttribute); + } + rTreeCtrl.Expand(pEntry); + + rWalker.get_children(aNames); + + // Non-leaf if it has child elements, leaf otherwise. + rEntryData.mbLeafNode = aNames.empty(); + + // Insert child elements recursively. + for (it = aNames.begin(), itEnd = aNames.end(); it != itEnd; ++it) + { + orcus::xml_structure_tree::element aElem = rWalker.descend(*it); + populateTree(rTreeCtrl, rWalker, *it, aElem.repeat, pEntry, rParam); + rWalker.ascend(); + } +} + +class TreeUpdateSwitch +{ + SvTreeListBox& mrTreeCtrl; +public: + TreeUpdateSwitch(SvTreeListBox& rTreeCtrl) : mrTreeCtrl(rTreeCtrl) + { + mrTreeCtrl.SetUpdateMode(false); + } + + ~TreeUpdateSwitch() + { + mrTreeCtrl.SetUpdateMode(true); + } +}; + +class InsertFieldPath : std::unary_function<OString, void> +{ + orcus::orcus_xml& mrFilter; +public: + InsertFieldPath(orcus::orcus_xml& rFilter) : mrFilter(rFilter) {} + void operator() (const OString& rPath) + { + mrFilter.append_field_link(rPath.getStr()); + } +}; + +} + +ScOrcusXMLContextImpl::ScOrcusXMLContextImpl(ScDocument& rDoc, const OUString& rPath) : + ScOrcusXMLContext(), mrDoc(rDoc), maPath(rPath) {} + +ScOrcusXMLContextImpl::~ScOrcusXMLContextImpl() {} + +bool ScOrcusXMLContextImpl::loadXMLStructure(SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const +{ + rParam.maUserDataStore.clear(); + + OString aSysPath = ScOrcusFiltersImpl::toSystemPath(maPath); + const char* path = aSysPath.getStr(); + + // TODO: Use our own stream loading call instead of one from orcus. + std::string aStrm; + orcus::load_file_content(path, aStrm); + + if (aStrm.empty()) + return false; + + orcus::xmlns_repository repo; // xml namespace repository. + orcus::xmlns_context cxt = repo.create_context(); + orcus::xml_structure_tree aXmlTree(cxt); + try + { + aXmlTree.parse(&aStrm[0], aStrm.size()); + + TreeUpdateSwitch aSwitch(rTreeCtrl); + rTreeCtrl.Clear(); + rTreeCtrl.SetDefaultCollapsedEntryBmp(rParam.maImgElementDefault); + rTreeCtrl.SetDefaultExpandedEntryBmp(rParam.maImgElementDefault); + + orcus::xml_structure_tree::walker aWalker = aXmlTree.get_walker(); + + // Root element. + orcus::xml_structure_tree::element aElem = aWalker.root(); + populateTree(rTreeCtrl, aWalker, aElem.name, aElem.repeat, NULL, rParam); + } + catch (const std::exception&) + { + // Parsing of this XML file failed. + return false; + } + + return true; +} + +bool ScOrcusXMLContextImpl::importXML(const ScOrcusImportXMLParam& rParam) const +{ + ScOrcusFactory aFactory(mrDoc); + OString aSysPath = ScOrcusFiltersImpl::toSystemPath(maPath); + const char* path = aSysPath.getStr(); + try + { + orcus::orcus_xml filter(&aFactory, NULL); + + // Set cell links. + { + ScOrcusImportXMLParam::CellLinksType::const_iterator it = rParam.maCellLinks.begin(); + ScOrcusImportXMLParam::CellLinksType::const_iterator itEnd = rParam.maCellLinks.end(); + for (; it != itEnd; ++it) + { + const ScOrcusImportXMLParam::CellLink& rLink = *it; + OUString aTabName; + mrDoc.GetName(rLink.maPos.Tab(), aTabName); + filter.set_cell_link( + rLink.maPath.getStr(), + rtl::OUStringToOString(aTabName, RTL_TEXTENCODING_UTF8).getStr(), + rLink.maPos.Row(), rLink.maPos.Col()); + } + } + + // Set range links. + { + ScOrcusImportXMLParam::RangeLinksType::const_iterator it = rParam.maRangeLinks.begin(); + ScOrcusImportXMLParam::RangeLinksType::const_iterator itEnd = rParam.maRangeLinks.end(); + for (; it != itEnd; ++it) + { + const ScOrcusImportXMLParam::RangeLink& rLink = *it; + OUString aTabName; + mrDoc.GetName(rLink.maPos.Tab(), aTabName); + filter.start_range( + rtl::OUStringToOString(aTabName, RTL_TEXTENCODING_UTF8).getStr(), + rLink.maPos.Row(), rLink.maPos.Col()); + + std::for_each(rLink.maFieldPaths.begin(), rLink.maFieldPaths.end(), InsertFieldPath(filter)); + + filter.commit_range(); + } + } + + filter.read_file(path); + } + catch (const std::exception&) + { + return false; + } + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |