Update ooo320-m1
[ooovba.git] / sc / source / filter / xml / xmlexternaltabi.cxx
blobb953b26b26f774cea1015e85d11ad59d2f84d4f7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlexternaltabi.cxx,v $
10 * $Revision: 1.1.2.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "xmlexternaltabi.hxx"
39 #include "xmlimprt.hxx"
40 #include "xmltabi.hxx"
41 #include "xmlstyli.hxx"
43 #include "token.hxx"
44 #include "document.hxx"
46 #include <xmloff/nmspmap.hxx>
47 #include <xmloff/xmlnmspe.hxx>
48 #include <xmloff/xmltoken.hxx>
49 #include <xmloff/xmluconv.hxx>
50 #include <com/sun/star/util/NumberFormat.hpp>
52 using namespace ::com::sun::star;
54 using ::rtl::OUString;
55 using ::com::sun::star::uno::Reference;
56 using ::com::sun::star::xml::sax::XAttributeList;
58 // ============================================================================
60 ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
61 ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
62 const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
63 SvXMLImportContext( rImport, nPrefix, rLName ),
64 mrScImport(rImport),
65 mrExternalRefInfo(rRefInfo)
67 using namespace ::xmloff::token;
69 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
70 for (sal_Int16 i = 0; i < nAttrCount; ++i)
72 const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
73 rtl::OUString aLocalName;
74 sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
75 const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
76 if (nAttrPrefix == XML_NAMESPACE_XLINK)
78 if (IsXMLToken(aLocalName, XML_HREF))
79 maRelativeUrl = sValue;
81 else if (nAttrPrefix == XML_NAMESPACE_TABLE)
83 if (IsXMLToken(aLocalName, XML_TABLE_NAME))
84 maTableName = sValue;
85 else if (IsXMLToken(aLocalName, XML_FILTER_NAME))
86 maFilterName = sValue;
87 else if (IsXMLToken(aLocalName, XML_FILTER_OPTIONS))
88 maFilterOptions = sValue;
93 ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
97 SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
98 USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
100 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
103 /**
104 * Make sure the URL is a valid relative URL, mainly to avoid storing
105 * absolute URL as relative URL by accident. For now, we only check the first
106 * three characters which are assumed to be always '../', because the relative
107 * URL for an external document is always in reference to the content.xml
108 * fragment of the original document.
110 static bool lcl_isValidRelativeURL(const OUString& rUrl)
112 sal_Int32 n = ::std::min( rUrl.getLength(), static_cast<sal_Int32>(3));
113 if (n < 3)
114 return false;
115 const sal_Unicode* p = rUrl.getStr();
116 for (sal_Int32 i = 0; i < n; ++i)
118 sal_Unicode c = p[i];
119 if (i < 2 && c != '.')
120 // the path must begin with '..'
121 return false;
122 else if (i == 2 && c != '/')
123 // a '/' path separator must follow
124 return false;
126 return true;
129 void ScXMLExternalRefTabSourceContext::EndElement()
131 ScDocument* pDoc = mrScImport.GetDocument();
132 if (!pDoc)
133 return;
135 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
136 if (lcl_isValidRelativeURL(maRelativeUrl))
137 pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
138 pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
141 // ============================================================================
143 ScXMLExternalRefRowsContext::ScXMLExternalRefRowsContext(
144 ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
145 const Reference<XAttributeList>& /* xAttrList */, ScXMLExternalTabData& rRefInfo ) :
146 SvXMLImportContext( rImport, nPrefix, rLName ),
147 mrScImport(rImport),
148 mrExternalRefInfo(rRefInfo)
152 ScXMLExternalRefRowsContext::~ScXMLExternalRefRowsContext()
156 SvXMLImportContext* ScXMLExternalRefRowsContext::CreateChildContext(
157 USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
159 // #i101319# row elements inside group, rows or header-rows
160 // are treated like row elements directly in the table element
162 const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowsElemTokenMap();
163 sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
164 switch (nToken)
166 case XML_TOK_TABLE_ROWS_ROW_GROUP:
167 case XML_TOK_TABLE_ROWS_HEADER_ROWS:
168 case XML_TOK_TABLE_ROWS_ROWS:
169 return new ScXMLExternalRefRowsContext(
170 mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
171 case XML_TOK_TABLE_ROWS_ROW:
172 return new ScXMLExternalRefRowContext(
173 mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
174 default:
177 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
180 void ScXMLExternalRefRowsContext::EndElement()
184 // ============================================================================
186 ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
187 ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
188 const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
189 SvXMLImportContext( rImport, nPrefix, rLName ),
190 mrScImport(rImport),
191 mrExternalRefInfo(rRefInfo),
192 mnRepeatRowCount(1)
194 mrExternalRefInfo.mnCol = 0;
196 sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
197 const SvXMLTokenMap& rAttrTokenMap = mrScImport.GetTableRowAttrTokenMap();
198 for( sal_Int16 i=0; i < nAttrCount; ++i )
200 const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
201 rtl::OUString aLocalName;
202 sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
203 const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
205 switch (rAttrTokenMap.Get(nAttrPrefix, aLocalName))
207 case XML_TOK_TABLE_ROW_ATTR_REPEATED:
209 mnRepeatRowCount = std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
211 break;
216 ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
220 SvXMLImportContext* ScXMLExternalRefRowContext::CreateChildContext(
221 USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
223 const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowElemTokenMap();
224 sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
225 if (nToken == XML_TOK_TABLE_ROW_CELL || nToken == XML_TOK_TABLE_ROW_COVERED_CELL)
226 return new ScXMLExternalRefCellContext(mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
228 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
231 void ScXMLExternalRefRowContext::EndElement()
233 ScExternalRefCache::TableTypeRef pTab = mrExternalRefInfo.mpCacheTable;
235 for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i)
237 // Performance: duplicates of a non-existent row will still not exist.
238 // Don't find that out for every cell.
239 // External references often are a sparse matrix.
240 if (i == 1 && !pTab->hasRow( mrExternalRefInfo.mnRow))
242 mrExternalRefInfo.mnRow += mnRepeatRowCount;
243 return;
246 for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
248 ScExternalRefCache::TokenRef pToken = pTab->getCell(
249 static_cast<SCCOL>(j), static_cast<SCROW>(mrExternalRefInfo.mnRow));
251 if (pToken.get())
253 pTab->setCell(static_cast<SCCOL>(j),
254 static_cast<SCROW>(mrExternalRefInfo.mnRow+i), pToken);
258 mrExternalRefInfo.mnRow += mnRepeatRowCount;
261 // ============================================================================
263 ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
264 ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
265 const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
266 SvXMLImportContext( rImport, nPrefix, rLName ),
267 mrScImport(rImport),
268 mrExternalRefInfo(rRefInfo),
269 mfCellValue(0.0),
270 mnRepeatCount(1),
271 mnNumberFormat(-1),
272 mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
273 mbIsNumeric(false),
274 mbIsEmpty(true)
276 using namespace ::xmloff::token;
278 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
279 const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
280 for (sal_Int16 i = 0; i < nAttrCount; ++i)
282 OUString aLocalName;
283 sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
284 xAttrList->getNameByIndex(i), &aLocalName);
286 const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
287 sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
289 switch (nToken)
291 case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
293 XMLTableStylesContext* pStyles = static_cast<XMLTableStylesContext*>(mrScImport.GetAutoStyles());
294 const XMLTableStyleContext* pStyle = static_cast<const XMLTableStyleContext*>(
295 pStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_CELL, sValue, true));
296 if (pStyle)
297 mnNumberFormat = const_cast<XMLTableStyleContext*>(pStyle)->GetNumberFormat();
299 break;
300 case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
302 mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
304 break;
305 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
307 mnCellType = mrScImport.GetCellType(sValue);
309 break;
310 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
312 if (sValue.getLength())
314 mrScImport.GetMM100UnitConverter().convertDouble(mfCellValue, sValue);
315 mbIsNumeric = true;
316 mbIsEmpty = false;
319 break;
320 case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
322 if (sValue.getLength() && mrScImport.SetNullDateOnUnitConverter())
324 mrScImport.GetMM100UnitConverter().convertDateTime(mfCellValue, sValue);
325 mbIsNumeric = true;
326 mbIsEmpty = false;
329 break;
330 case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
332 if (sValue.getLength())
334 mrScImport.GetMM100UnitConverter().convertTime(mfCellValue, sValue);
335 mbIsNumeric = true;
336 mbIsEmpty = false;
339 break;
340 case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
342 if (sValue.getLength())
344 maCellString = sValue;
345 mbIsNumeric = false;
346 mbIsEmpty = false;
349 break;
350 case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
352 if (sValue.getLength())
354 mfCellValue = IsXMLToken(sValue, XML_TRUE) ? 1.0 : 0.0;
355 mbIsNumeric = true;
356 mbIsEmpty = false;
359 break;
360 default:
366 ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
370 SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext(
371 USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
373 const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowCellElemTokenMap();
374 sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
375 if (nToken == XML_TOK_TABLE_ROW_CELL_P)
376 return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, maCellString);
378 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
381 void ScXMLExternalRefCellContext::EndElement()
383 if (maCellString.getLength())
384 mbIsEmpty = false;
386 for (sal_Int32 i = 0; i < mnRepeatCount; ++i, ++mrExternalRefInfo.mnCol)
388 if (mbIsEmpty)
389 continue;
391 ScExternalRefCache::TokenRef aToken;
392 if (mbIsNumeric)
393 aToken.reset(new formula::FormulaDoubleToken(mfCellValue));
394 else
395 aToken.reset(new formula::FormulaStringToken(maCellString));
397 sal_uInt32 nNumFmt = mnNumberFormat >= 0 ? static_cast<sal_uInt32>(mnNumberFormat) : 0;
398 mrExternalRefInfo.mpCacheTable->setCell(
399 static_cast<SCCOL>(mrExternalRefInfo.mnCol),
400 static_cast<SCROW>(mrExternalRefInfo.mnRow),
401 aToken, nNumFmt);
405 // ============================================================================
407 ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
408 ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
409 const Reference<XAttributeList>& /*xAttrList*/, OUString& rCellString ) :
410 SvXMLImportContext( rImport, nPrefix, rLName ),
411 mrScImport(rImport),
412 mrCellString(rCellString)
416 ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
420 SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext(
421 USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
423 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
426 void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar)
428 mrCellString = rChar;
431 void ScXMLExternalRefCellTextContext::EndElement()