Kaydet (Commit) 1157cbc9 authored tarafından Kohei Yoshida's avatar Kohei Yoshida

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
üst 83c2f4c8
...@@ -221,7 +221,9 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\ ...@@ -221,7 +221,9 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
sc/source/filter/oox/worksheethelper \ sc/source/filter/oox/worksheethelper \
sc/source/filter/oox/worksheetsettings \ sc/source/filter/oox/worksheetsettings \
sc/source/filter/orcus/orcusfiltersimpl \ sc/source/filter/orcus/orcusfiltersimpl \
sc/source/filter/orcus/interface \
sc/source/filter/orcus/orcusxml \ sc/source/filter/orcus/orcusxml \
sc/source/filter/orcus/xmlcontext \
)) ))
ifeq ($(SYSTEM_ZLIB),YES) ifeq ($(SYSTEM_ZLIB),YES)
......
...@@ -17,6 +17,7 @@ class SvTreeListBox; ...@@ -17,6 +17,7 @@ class SvTreeListBox;
class Image; class Image;
struct ScOrcusXMLTreeParam; struct ScOrcusXMLTreeParam;
struct ScOrcusImportXMLParam; struct ScOrcusImportXMLParam;
class ScOrcusXMLContext;
/** /**
* Collection of orcus filter wrappers. * Collection of orcus filter wrappers.
...@@ -28,11 +29,17 @@ public: ...@@ -28,11 +29,17 @@ public:
virtual bool importCSV(ScDocument& rDoc, const rtl::OUString& rPath) const = 0; virtual bool importCSV(ScDocument& rDoc, const rtl::OUString& rPath) const = 0;
virtual bool loadXMLStructure( virtual ScOrcusXMLContext* createXMLContext(ScDocument& rDoc, const rtl::OUString& rPath) const = 0;
const rtl::OUString& rPath, SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const = 0; };
class ScOrcusXMLContext
{
public:
virtual ~ScOrcusXMLContext() {}
virtual bool loadXMLStructure(SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) const = 0;
virtual bool importXML( virtual bool importXML(const ScOrcusImportXMLParam& rParam) const = 0;
ScDocument& rDoc, const rtl::OUString& rPath, const ScOrcusImportXMLParam& rParam) const = 0;
}; };
#endif #endif
......
...@@ -15,13 +15,24 @@ ...@@ -15,13 +15,24 @@
class ScOrcusFiltersImpl : public ScOrcusFilters class ScOrcusFiltersImpl : public ScOrcusFilters
{ {
public: public:
static rtl::OString toSystemPath(const rtl::OUString& rPath);
virtual bool importCSV(ScDocument& rDoc, const rtl::OUString& rPath) const; virtual bool importCSV(ScDocument& rDoc, const rtl::OUString& rPath) const;
virtual bool loadXMLStructure( virtual ScOrcusXMLContext* createXMLContext(ScDocument& rDoc, const rtl::OUString& rPath) const;
const rtl::OUString& rPath, SvTreeListBox& rTreeCtrl, ScOrcusXMLTreeParam& rParam) 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( virtual bool importXML(const ScOrcusImportXMLParam& rParam) const;
ScDocument& rDoc, const rtl::OUString& rPath, const ScOrcusImportXMLParam& rParam) const;
}; };
#endif #endif
......
/* -*- 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: */
/* -*- 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: */
/* -*- 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: */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
class ScDocument; class ScDocument;
class ScRange; class ScRange;
class ScOrcusXMLContext;
class ScXMLSourceTree : public SvTreeListBox class ScXMLSourceTree : public SvTreeListBox
{ {
...@@ -55,6 +56,8 @@ class ScXMLSourceDlg : public ScAnyRefDlg ...@@ -55,6 +56,8 @@ class ScXMLSourceDlg : public ScAnyRefDlg
std::set<const SvTreeListEntry*> maCellLinks; std::set<const SvTreeListEntry*> maCellLinks;
std::set<const SvTreeListEntry*> maRangeLinks; std::set<const SvTreeListEntry*> maRangeLinks;
boost::scoped_ptr<ScOrcusXMLContext> mpXMLContext;
ScDocument* mpDoc; ScDocument* mpDoc;
formula::RefEdit* mpActiveEdit; formula::RefEdit* mpActiveEdit;
......
...@@ -208,7 +208,11 @@ void ScXMLSourceDlg::LoadSourceFileStructure(const OUString& rPath) ...@@ -208,7 +208,11 @@ void ScXMLSourceDlg::LoadSourceFileStructure(const OUString& rPath)
if (!pOrcus) if (!pOrcus)
return; return;
pOrcus->loadXMLStructure(rPath, maLbTree, maXMLParam); mpXMLContext.reset(pOrcus->createXMLContext(*mpDoc, rPath));
if (!mpXMLContext)
return;
mpXMLContext->loadXMLStructure(maLbTree, maXMLParam);
} }
void ScXMLSourceDlg::HandleGetFocus(Control* pCtrl) void ScXMLSourceDlg::HandleGetFocus(Control* pCtrl)
...@@ -454,6 +458,9 @@ void getFieldLinks(ScOrcusImportXMLParam::RangeLink& rRangeLink, const SvTreeLis ...@@ -454,6 +458,9 @@ void getFieldLinks(ScOrcusImportXMLParam::RangeLink& rRangeLink, const SvTreeLis
void ScXMLSourceDlg::OkPressed() void ScXMLSourceDlg::OkPressed()
{ {
if (!mpXMLContext)
return;
// Begin import. // Begin import.
ScOrcusImportXMLParam aParam; ScOrcusImportXMLParam aParam;
...@@ -493,11 +500,8 @@ void ScXMLSourceDlg::OkPressed() ...@@ -493,11 +500,8 @@ void ScXMLSourceDlg::OkPressed()
} }
// Now do the import. // Now do the import.
ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters();
if (!pOrcus)
return;
pOrcus->importXML(*mpDoc, maSrcPath, aParam); mpXMLContext->importXML(aParam);
// Don't forget to broadcast the change. // Don't forget to broadcast the change.
SfxObjectShell* pShell = mpDoc->GetDocumentShell(); SfxObjectShell* pShell = mpDoc->GetDocumentShell();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment