Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "xmlexternaltabi.hxx"
21 : #include "xmlimprt.hxx"
22 : #include "xmltabi.hxx"
23 : #include "xmlstyli.hxx"
24 :
25 : #include "token.hxx"
26 : #include "document.hxx"
27 :
28 : #include <xmloff/nmspmap.hxx>
29 : #include <xmloff/xmlnmspe.hxx>
30 : #include <xmloff/xmltoken.hxx>
31 : #include <xmloff/xmluconv.hxx>
32 :
33 : #include <sax/tools/converter.hxx>
34 :
35 : #include <com/sun/star/util/NumberFormat.hpp>
36 :
37 : using namespace ::com::sun::star;
38 :
39 : using ::com::sun::star::uno::Reference;
40 : using ::com::sun::star::xml::sax::XAttributeList;
41 :
42 : // ============================================================================
43 :
44 0 : ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
45 : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
46 : const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
47 : SvXMLImportContext( rImport, nPrefix, rLName ),
48 : mrScImport(rImport),
49 0 : mrExternalRefInfo(rRefInfo)
50 : {
51 : using namespace ::xmloff::token;
52 :
53 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
54 0 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
55 : {
56 0 : const OUString& sAttrName = xAttrList->getNameByIndex(i);
57 0 : OUString aLocalName;
58 0 : sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
59 0 : const OUString& sValue = xAttrList->getValueByIndex(i);
60 0 : if (nAttrPrefix == XML_NAMESPACE_XLINK)
61 : {
62 0 : if (IsXMLToken(aLocalName, XML_HREF))
63 0 : maRelativeUrl = sValue;
64 : }
65 0 : else if (nAttrPrefix == XML_NAMESPACE_TABLE)
66 : {
67 0 : if (IsXMLToken(aLocalName, XML_TABLE_NAME))
68 0 : maTableName = sValue;
69 0 : else if (IsXMLToken(aLocalName, XML_FILTER_NAME))
70 0 : maFilterName = sValue;
71 0 : else if (IsXMLToken(aLocalName, XML_FILTER_OPTIONS))
72 0 : maFilterOptions = sValue;
73 : }
74 0 : }
75 0 : }
76 :
77 0 : ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
78 : {
79 0 : }
80 :
81 0 : SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
82 : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
83 : {
84 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
85 : }
86 :
87 : /**
88 : * Make sure the URL is a valid relative URL, mainly to avoid storing
89 : * absolute URL as relative URL by accident. For now, we only check the first
90 : * three characters which are assumed to be always '../', because the relative
91 : * URL for an external document is always in reference to the content.xml
92 : * fragment of the original document.
93 : */
94 0 : static bool lcl_isValidRelativeURL(const OUString& rUrl)
95 : {
96 0 : sal_Int32 n = ::std::min( rUrl.getLength(), static_cast<sal_Int32>(3));
97 0 : if (n < 3)
98 0 : return false;
99 0 : const sal_Unicode* p = rUrl.getStr();
100 0 : for (sal_Int32 i = 0; i < n; ++i)
101 : {
102 0 : sal_Unicode c = p[i];
103 0 : if (i < 2 && c != '.')
104 : // the path must begin with '..'
105 0 : return false;
106 0 : else if (i == 2 && c != '/')
107 : // a '/' path separator must follow
108 0 : return false;
109 : }
110 0 : return true;
111 : }
112 :
113 0 : void ScXMLExternalRefTabSourceContext::EndElement()
114 : {
115 0 : ScDocument* pDoc = mrScImport.GetDocument();
116 0 : if (!pDoc)
117 0 : return;
118 :
119 0 : ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
120 0 : if (lcl_isValidRelativeURL(maRelativeUrl))
121 0 : pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
122 0 : pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
123 : }
124 :
125 : // ============================================================================
126 :
127 0 : ScXMLExternalRefRowsContext::ScXMLExternalRefRowsContext(
128 : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
129 : const Reference<XAttributeList>& /* xAttrList */, ScXMLExternalTabData& rRefInfo ) :
130 : SvXMLImportContext( rImport, nPrefix, rLName ),
131 : mrScImport(rImport),
132 0 : mrExternalRefInfo(rRefInfo)
133 : {
134 0 : }
135 :
136 0 : ScXMLExternalRefRowsContext::~ScXMLExternalRefRowsContext()
137 : {
138 0 : }
139 :
140 0 : SvXMLImportContext* ScXMLExternalRefRowsContext::CreateChildContext(
141 : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
142 : {
143 : // #i101319# row elements inside group, rows or header-rows
144 : // are treated like row elements directly in the table element
145 :
146 0 : const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowsElemTokenMap();
147 0 : sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
148 0 : switch (nToken)
149 : {
150 : case XML_TOK_TABLE_ROWS_ROW_GROUP:
151 : case XML_TOK_TABLE_ROWS_HEADER_ROWS:
152 : case XML_TOK_TABLE_ROWS_ROWS:
153 : return new ScXMLExternalRefRowsContext(
154 0 : mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
155 : case XML_TOK_TABLE_ROWS_ROW:
156 : return new ScXMLExternalRefRowContext(
157 0 : mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
158 : default:
159 : ;
160 : }
161 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
162 : }
163 :
164 0 : void ScXMLExternalRefRowsContext::EndElement()
165 : {
166 0 : }
167 :
168 : // ============================================================================
169 :
170 0 : ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
171 : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
172 : const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
173 : SvXMLImportContext( rImport, nPrefix, rLName ),
174 : mrScImport(rImport),
175 : mrExternalRefInfo(rRefInfo),
176 0 : mnRepeatRowCount(1)
177 : {
178 0 : mrExternalRefInfo.mnCol = 0;
179 :
180 0 : sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
181 0 : const SvXMLTokenMap& rAttrTokenMap = mrScImport.GetTableRowAttrTokenMap();
182 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
183 : {
184 0 : const OUString& sAttrName = xAttrList->getNameByIndex(i);
185 0 : OUString aLocalName;
186 0 : sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
187 0 : const OUString& sValue = xAttrList->getValueByIndex(i);
188 :
189 0 : switch (rAttrTokenMap.Get(nAttrPrefix, aLocalName))
190 : {
191 : case XML_TOK_TABLE_ROW_ATTR_REPEATED:
192 : {
193 0 : mnRepeatRowCount = std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
194 : }
195 0 : break;
196 : }
197 0 : }
198 0 : }
199 :
200 0 : ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
201 : {
202 0 : }
203 :
204 0 : SvXMLImportContext* ScXMLExternalRefRowContext::CreateChildContext(
205 : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
206 : {
207 0 : const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowElemTokenMap();
208 0 : sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
209 0 : if (nToken == XML_TOK_TABLE_ROW_CELL || nToken == XML_TOK_TABLE_ROW_COVERED_CELL)
210 0 : return new ScXMLExternalRefCellContext(mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
211 :
212 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
213 : }
214 :
215 0 : void ScXMLExternalRefRowContext::EndElement()
216 : {
217 0 : ScExternalRefCache::TableTypeRef pTab = mrExternalRefInfo.mpCacheTable;
218 :
219 0 : for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i)
220 : {
221 : // Performance: duplicates of a non-existent row will still not exist.
222 : // Don't find that out for every cell.
223 : // External references often are a sparse matrix.
224 0 : if (i == 1 && !pTab->hasRow( mrExternalRefInfo.mnRow))
225 : {
226 0 : mrExternalRefInfo.mnRow += mnRepeatRowCount;
227 0 : return;
228 : }
229 :
230 0 : for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
231 : {
232 : ScExternalRefCache::TokenRef pToken = pTab->getCell(
233 0 : static_cast<SCCOL>(j), static_cast<SCROW>(mrExternalRefInfo.mnRow));
234 :
235 0 : if (pToken.get())
236 : {
237 : pTab->setCell(static_cast<SCCOL>(j),
238 0 : static_cast<SCROW>(mrExternalRefInfo.mnRow+i), pToken);
239 : }
240 0 : }
241 : }
242 0 : mrExternalRefInfo.mnRow += mnRepeatRowCount;
243 : }
244 :
245 : // ============================================================================
246 :
247 0 : ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
248 : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
249 : const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
250 : SvXMLImportContext( rImport, nPrefix, rLName ),
251 : mrScImport(rImport),
252 : mrExternalRefInfo(rRefInfo),
253 : mfCellValue(0.0),
254 : mnRepeatCount(1),
255 : mnNumberFormat(-1),
256 : mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
257 : mbIsNumeric(false),
258 0 : mbIsEmpty(true)
259 : {
260 : using namespace ::xmloff::token;
261 :
262 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
263 0 : const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
264 0 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
265 : {
266 0 : OUString aLocalName;
267 0 : sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
268 0 : xAttrList->getNameByIndex(i), &aLocalName);
269 :
270 0 : const OUString& sValue = xAttrList->getValueByIndex(i);
271 0 : sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
272 :
273 0 : switch (nToken)
274 : {
275 : case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
276 : {
277 0 : XMLTableStylesContext* pStyles = static_cast<XMLTableStylesContext*>(mrScImport.GetAutoStyles());
278 : const XMLTableStyleContext* pStyle = static_cast<const XMLTableStyleContext*>(
279 0 : pStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_CELL, sValue, true));
280 0 : if (pStyle)
281 0 : mnNumberFormat = const_cast<XMLTableStyleContext*>(pStyle)->GetNumberFormat();
282 : }
283 0 : break;
284 : case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
285 : {
286 0 : mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
287 : }
288 0 : break;
289 : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
290 : {
291 0 : mnCellType = mrScImport.GetCellType(sValue);
292 : }
293 0 : break;
294 : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
295 : {
296 0 : if (!sValue.isEmpty())
297 : {
298 0 : ::sax::Converter::convertDouble(mfCellValue, sValue);
299 0 : mbIsNumeric = true;
300 0 : mbIsEmpty = false;
301 : }
302 : }
303 0 : break;
304 : case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
305 : {
306 0 : if (!sValue.isEmpty() && mrScImport.SetNullDateOnUnitConverter())
307 : {
308 0 : mrScImport.GetMM100UnitConverter().convertDateTime(mfCellValue, sValue);
309 0 : mbIsNumeric = true;
310 0 : mbIsEmpty = false;
311 : }
312 : }
313 0 : break;
314 : case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
315 : {
316 0 : if (!sValue.isEmpty())
317 : {
318 0 : ::sax::Converter::convertDuration(mfCellValue, sValue);
319 0 : mbIsNumeric = true;
320 0 : mbIsEmpty = false;
321 : }
322 : }
323 0 : break;
324 : case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
325 : {
326 0 : if (!sValue.isEmpty())
327 : {
328 0 : maCellString = sValue;
329 0 : mbIsNumeric = false;
330 0 : mbIsEmpty = false;
331 : }
332 : }
333 0 : break;
334 : case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
335 : {
336 0 : if (!sValue.isEmpty())
337 : {
338 0 : mfCellValue = IsXMLToken(sValue, XML_TRUE) ? 1.0 : 0.0;
339 0 : mbIsNumeric = true;
340 0 : mbIsEmpty = false;
341 : }
342 : }
343 0 : break;
344 : default:
345 : ;
346 : }
347 0 : }
348 0 : }
349 :
350 0 : ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
351 : {
352 0 : }
353 :
354 0 : SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext(
355 : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
356 : {
357 0 : const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowCellElemTokenMap();
358 0 : sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
359 0 : if (nToken == XML_TOK_TABLE_ROW_CELL_P)
360 0 : return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, *this);
361 :
362 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
363 : }
364 :
365 0 : void ScXMLExternalRefCellContext::EndElement()
366 : {
367 0 : if (!maCellString.isEmpty())
368 0 : mbIsEmpty = false;
369 :
370 0 : for (sal_Int32 i = 0; i < mnRepeatCount; ++i, ++mrExternalRefInfo.mnCol)
371 : {
372 0 : if (mbIsEmpty)
373 0 : continue;
374 :
375 0 : ScExternalRefCache::TokenRef aToken;
376 0 : if (mbIsNumeric)
377 0 : aToken.reset(new formula::FormulaDoubleToken(mfCellValue));
378 : else
379 0 : aToken.reset(new formula::FormulaStringToken(maCellString));
380 :
381 0 : sal_uInt32 nNumFmt = mnNumberFormat >= 0 ? static_cast<sal_uInt32>(mnNumberFormat) : 0;
382 : mrExternalRefInfo.mpCacheTable->setCell(
383 : static_cast<SCCOL>(mrExternalRefInfo.mnCol),
384 : static_cast<SCROW>(mrExternalRefInfo.mnRow),
385 0 : aToken, nNumFmt);
386 0 : }
387 0 : }
388 :
389 0 : void ScXMLExternalRefCellContext::SetCellString(const OUString& rStr)
390 : {
391 0 : maCellString = rStr;
392 0 : }
393 :
394 : // ============================================================================
395 :
396 0 : ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
397 : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
398 : const Reference<XAttributeList>& /*xAttrList*/,
399 : ScXMLExternalRefCellContext& rParent ) :
400 : SvXMLImportContext( rImport, nPrefix, rLName ),
401 0 : mrParent(rParent)
402 : {
403 0 : }
404 :
405 0 : ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
406 : {
407 0 : }
408 :
409 0 : SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext(
410 : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
411 : {
412 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
413 : }
414 :
415 0 : void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar)
416 : {
417 0 : maCellStrBuf.append(rChar);
418 0 : }
419 :
420 0 : void ScXMLExternalRefCellTextContext::EndElement()
421 : {
422 0 : mrParent.SetCellString(maCellStrBuf.makeStringAndClear());
423 93 : }
424 :
425 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|