1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "xmlexternaltabi.hxx"
21 #include "xmlimprt.hxx"
22 #include "xmltabi.hxx"
23 #include "xmlstyli.hxx"
25 #include <document.hxx>
26 #include <documentimport.hxx>
28 #include <svl/sharedstringpool.hxx>
29 #include <xmloff/xmlnmspe.hxx>
30 #include <xmloff/xmltoken.hxx>
31 #include <xmloff/xmluconv.hxx>
33 #include <sax/tools/converter.hxx>
35 #include <com/sun/star/util/NumberFormat.hpp>
37 using namespace ::com::sun::star
;
38 using namespace ::com::sun::star::xml::sax
;
40 using ::com::sun::star::uno::Reference
;
42 ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
44 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
, ScXMLExternalTabData
& rRefInfo
) :
45 ScXMLImportContext( rImport
),
46 mrExternalRefInfo(rRefInfo
)
48 using namespace ::xmloff::token
;
52 for (auto &it
: *rAttrList
)
54 sal_Int32 nAttrToken
= it
.getToken();
55 if ( nAttrToken
== XML_ELEMENT( XLINK
, XML_HREF
) )
56 maRelativeUrl
= it
.toString();
57 else if ( nAttrToken
== XML_ELEMENT( TABLE
, XML_TABLE_NAME
) )
60 else if ( nAttrToken
== XML_ELEMENT( TABLE
, XML_FILTER_NAME
) )
61 maFilterName
= it
.toString();
62 else if ( nAttrToken
== XML_ELEMENT( TABLE
, XML_FILTER_OPTIONS
) )
63 maFilterOptions
= it
.toString();
68 ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
73 * Make sure the URL is a valid relative URL, mainly to avoid storing
74 * absolute URL as relative URL by accident. For now, we only check the first
75 * three characters which are assumed to be always '../', because the relative
76 * URL for an external document is always in reference to the content.xml
77 * fragment of the original document.
79 static bool lcl_isValidRelativeURL(const OUString
& rUrl
)
81 sal_Int32 n
= ::std::min( rUrl
.getLength(), static_cast<sal_Int32
>(3));
84 const sal_Unicode
* p
= rUrl
.getStr();
85 for (sal_Int32 i
= 0; i
< n
; ++i
)
88 if (i
< 2 && c
!= '.')
89 // the path must begin with '..'
91 else if (i
== 2 && c
!= '/')
92 // a '/' path separator must follow
98 void SAL_CALL
ScXMLExternalRefTabSourceContext::endFastElement( sal_Int32
/*nElement*/ )
100 ScDocument
* pDoc
= GetScImport().GetDocument();
104 ScExternalRefManager
* pRefMgr
= pDoc
->GetExternalRefManager();
105 if (lcl_isValidRelativeURL(maRelativeUrl
))
106 pRefMgr
->setRelativeFileName(mrExternalRefInfo
.mnFileId
, maRelativeUrl
);
107 pRefMgr
->setFilterData(mrExternalRefInfo
.mnFileId
, maFilterName
, maFilterOptions
);
110 ScXMLExternalRefRowsContext::ScXMLExternalRefRowsContext(
111 ScXMLImport
& rImport
, ScXMLExternalTabData
& rRefInfo
) :
112 ScXMLImportContext( rImport
),
113 mrExternalRefInfo(rRefInfo
)
117 ScXMLExternalRefRowsContext::~ScXMLExternalRefRowsContext()
121 Reference
< XFastContextHandler
> SAL_CALL
ScXMLExternalRefRowsContext::createFastChildContext(
122 sal_Int32 nElement
, const Reference
< XFastAttributeList
>& xAttrList
)
124 // #i101319# row elements inside group, rows or header-rows
125 // are treated like row elements directly in the table element
127 const SvXMLTokenMap
& rTokenMap
= GetScImport().GetTableRowsElemTokenMap();
128 sal_uInt16 nToken
= rTokenMap
.Get( nElement
);
129 sax_fastparser::FastAttributeList
*pAttribList
=
130 sax_fastparser::FastAttributeList::castToFastAttributeList( xAttrList
);
134 case XML_TOK_TABLE_ROWS_ROW_GROUP
:
135 case XML_TOK_TABLE_ROWS_HEADER_ROWS
:
136 case XML_TOK_TABLE_ROWS_ROWS
:
137 return new ScXMLExternalRefRowsContext(
138 GetScImport(), mrExternalRefInfo
);
139 case XML_TOK_TABLE_ROWS_ROW
:
140 return new ScXMLExternalRefRowContext(
141 GetScImport(), pAttribList
, mrExternalRefInfo
);
145 return new SvXMLImportContext( GetImport() );
148 ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
149 ScXMLImport
& rImport
,
150 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
, ScXMLExternalTabData
& rRefInfo
) :
151 ScXMLImportContext( rImport
),
153 mrExternalRefInfo(rRefInfo
),
156 mrExternalRefInfo
.mnCol
= 0;
158 const SvXMLTokenMap
& rAttrTokenMap
= mrScImport
.GetTableRowAttrTokenMap();
159 if ( rAttrList
.is() )
161 for (auto &it
: *rAttrList
)
163 switch ( rAttrTokenMap
.Get( it
.getToken() ) )
165 case XML_TOK_TABLE_ROW_ATTR_REPEATED
:
167 mnRepeatRowCount
= std::max(it
.toInt32(), static_cast<sal_Int32
>(1));
175 ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
179 Reference
< XFastContextHandler
> SAL_CALL
ScXMLExternalRefRowContext::createFastChildContext(
180 sal_Int32 nElement
, const Reference
< XFastAttributeList
>& xAttrList
)
182 const SvXMLTokenMap
& rTokenMap
= mrScImport
.GetTableRowElemTokenMap();
183 sal_uInt16 nToken
= rTokenMap
.Get( nElement
);
184 sax_fastparser::FastAttributeList
*pAttribList
=
185 sax_fastparser::FastAttributeList::castToFastAttributeList( xAttrList
);
187 if (nToken
== XML_TOK_TABLE_ROW_CELL
|| nToken
== XML_TOK_TABLE_ROW_COVERED_CELL
)
188 return new ScXMLExternalRefCellContext(mrScImport
, pAttribList
, mrExternalRefInfo
);
190 return new SvXMLImportContext( GetImport() );
193 void SAL_CALL
ScXMLExternalRefRowContext::endFastElement( sal_Int32
/* nElement */ )
195 ScExternalRefCache::TableTypeRef pTab
= mrExternalRefInfo
.mpCacheTable
;
197 for (sal_Int32 i
= 1; i
< mnRepeatRowCount
; ++i
)
199 // Performance: duplicates of a non-existent row will still not exist.
200 // Don't find that out for every cell.
201 // External references often are a sparse matrix.
202 if (i
== 1 && !pTab
->hasRow( mrExternalRefInfo
.mnRow
))
204 mrExternalRefInfo
.mnRow
+= mnRepeatRowCount
;
208 for (sal_Int32 j
= 0; j
< mrExternalRefInfo
.mnCol
; ++j
)
210 ScExternalRefCache::TokenRef pToken
= pTab
->getCell(
211 static_cast<SCCOL
>(j
), static_cast<SCROW
>(mrExternalRefInfo
.mnRow
));
215 pTab
->setCell(static_cast<SCCOL
>(j
),
216 static_cast<SCROW
>(mrExternalRefInfo
.mnRow
+i
), pToken
);
220 mrExternalRefInfo
.mnRow
+= mnRepeatRowCount
;
223 ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
224 ScXMLImport
& rImport
,
225 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
, ScXMLExternalTabData
& rRefInfo
) :
226 ScXMLImportContext( rImport
),
228 mrExternalRefInfo(rRefInfo
),
232 mnCellType(css::util::NumberFormat::UNDEFINED
),
236 using namespace ::xmloff::token
;
238 const SvXMLTokenMap
& rTokenMap
= rImport
.GetTableRowCellAttrTokenMap();
239 if ( rAttrList
.is() )
241 for (auto &it
: *rAttrList
)
243 switch ( rTokenMap
.Get( it
.getToken() ) )
245 case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME
:
247 XMLTableStylesContext
* pStyles
= static_cast<XMLTableStylesContext
*>(mrScImport
.GetAutoStyles());
248 const XMLTableStyleContext
* pStyle
= static_cast<const XMLTableStyleContext
*>(
249 pStyles
->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_CELL
, it
.toString(), true));
251 mnNumberFormat
= const_cast<XMLTableStyleContext
*>(pStyle
)->GetNumberFormat();
254 case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED
:
256 mnRepeatCount
= ::std::max( it
.toInt32(), static_cast<sal_Int32
>(1) );
259 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE
:
261 mnCellType
= ScXMLImport::GetCellType( it
.toCString(), it
.getLength() );
264 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE
:
268 mfCellValue
= it
.toDouble();
274 case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE
:
276 if ( !it
.isEmpty() && mrScImport
.SetNullDateOnUnitConverter() )
278 mrScImport
.GetMM100UnitConverter().convertDateTime( mfCellValue
, it
.toString() );
284 case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE
:
288 ::sax::Converter::convertDuration( mfCellValue
, it
.toString() );
294 case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE
:
298 maCellString
= it
.toString();
304 case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE
:
308 mfCellValue
= IsXMLToken( it
, XML_TRUE
) ? 1.0 : 0.0;
321 ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
325 Reference
< XFastContextHandler
> SAL_CALL
ScXMLExternalRefCellContext::createFastChildContext(
326 sal_Int32 nElement
, const Reference
< XFastAttributeList
>& /*xAttrList*/ )
328 const SvXMLTokenMap
& rTokenMap
= mrScImport
.GetTableRowCellElemTokenMap();
329 sal_uInt16 nToken
= rTokenMap
.Get( nElement
);
331 if (nToken
== XML_TOK_TABLE_ROW_CELL_P
)
332 return new ScXMLExternalRefCellTextContext(mrScImport
, *this);
334 return new SvXMLImportContext( GetImport() );
337 void SAL_CALL
ScXMLExternalRefCellContext::endFastElement( sal_Int32
/*nElement*/ )
339 if (!maCellString
.isEmpty())
342 for (sal_Int32 i
= 0; i
< mnRepeatCount
; ++i
, ++mrExternalRefInfo
.mnCol
)
347 ScExternalRefCache::TokenRef aToken
;
349 aToken
.reset(new formula::FormulaDoubleToken(mfCellValue
));
352 ScDocument
& rDoc
= mrScImport
.GetDoc().getDoc();
353 svl::SharedString aSS
= rDoc
.GetSharedStringPool().intern(maCellString
);
354 aToken
.reset(new formula::FormulaStringToken(aSS
));
357 sal_uInt32 nNumFmt
= mnNumberFormat
>= 0 ? static_cast<sal_uInt32
>(mnNumberFormat
) : 0;
358 mrExternalRefInfo
.mpCacheTable
->setCell(
359 static_cast<SCCOL
>(mrExternalRefInfo
.mnCol
),
360 static_cast<SCROW
>(mrExternalRefInfo
.mnRow
),
365 void ScXMLExternalRefCellContext::SetCellString(const OUString
& rStr
)
370 ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
371 ScXMLImport
& rImport
,
372 ScXMLExternalRefCellContext
& rParent
) :
373 ScXMLImportContext( rImport
),
378 ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
382 void SAL_CALL
ScXMLExternalRefCellTextContext::characters( const OUString
& rChars
)
384 maCellStrBuf
.append( rChars
);
387 void SAL_CALL
ScXMLExternalRefCellTextContext::endFastElement( sal_Int32
/*nElement*/ )
389 mrParent
.SetCellString( maCellStrBuf
.makeStringAndClear() );
392 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */