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/xmlnamespace.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
;
39 using namespace ::xmloff::token
;
41 using ::com::sun::star::uno::Reference
;
43 ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
45 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
, ScXMLExternalTabData
& rRefInfo
) :
46 ScXMLImportContext( rImport
),
47 mrExternalRefInfo(rRefInfo
)
49 using namespace ::xmloff::token
;
51 if ( !rAttrList
.is() )
54 for (auto &it
: *rAttrList
)
56 sal_Int32 nAttrToken
= it
.getToken();
57 if ( nAttrToken
== XML_ELEMENT( XLINK
, XML_HREF
) )
58 maRelativeUrl
= it
.toString();
59 else if ( nAttrToken
== XML_ELEMENT( TABLE
, XML_TABLE_NAME
) )
62 else if ( nAttrToken
== XML_ELEMENT( TABLE
, XML_FILTER_NAME
) )
63 maFilterName
= it
.toString();
64 else if ( nAttrToken
== XML_ELEMENT( TABLE
, XML_FILTER_OPTIONS
) )
65 maFilterOptions
= it
.toString();
69 ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
74 * Make sure the URL is a valid relative URL, mainly to avoid storing
75 * absolute URL as relative URL by accident. For now, we only check the first
76 * three characters which are assumed to be always '../', because the relative
77 * URL for an external document is always in reference to the content.xml
78 * fragment of the original document.
80 static bool lcl_isValidRelativeURL(const OUString
& rUrl
)
82 sal_Int32 n
= ::std::min( rUrl
.getLength(), static_cast<sal_Int32
>(3));
85 const sal_Unicode
* p
= rUrl
.getStr();
86 for (sal_Int32 i
= 0; i
< n
; ++i
)
89 if (i
< 2 && c
!= '.')
90 // the path must begin with '..'
92 else if (i
== 2 && c
!= '/')
93 // a '/' path separator must follow
99 void SAL_CALL
ScXMLExternalRefTabSourceContext::endFastElement( sal_Int32
/*nElement*/ )
101 ScDocument
* pDoc
= GetScImport().GetDocument();
105 ScExternalRefManager
* pRefMgr
= pDoc
->GetExternalRefManager();
106 if (lcl_isValidRelativeURL(maRelativeUrl
))
107 pRefMgr
->setRelativeFileName(mrExternalRefInfo
.mnFileId
, maRelativeUrl
);
108 pRefMgr
->setFilterData(mrExternalRefInfo
.mnFileId
, maFilterName
, maFilterOptions
);
111 ScXMLExternalRefRowsContext::ScXMLExternalRefRowsContext(
112 ScXMLImport
& rImport
, ScXMLExternalTabData
& rRefInfo
) :
113 ScXMLImportContext( rImport
),
114 mrExternalRefInfo(rRefInfo
)
118 ScXMLExternalRefRowsContext::~ScXMLExternalRefRowsContext()
122 Reference
< XFastContextHandler
> SAL_CALL
ScXMLExternalRefRowsContext::createFastChildContext(
123 sal_Int32 nElement
, const Reference
< XFastAttributeList
>& xAttrList
)
125 // #i101319# row elements inside group, rows or header-rows
126 // are treated like row elements directly in the table element
128 sax_fastparser::FastAttributeList
*pAttribList
=
129 &sax_fastparser::castToFastAttributeList( xAttrList
);
133 case XML_ELEMENT(TABLE
, XML_TABLE_ROW_GROUP
):
134 case XML_ELEMENT(TABLE
, XML_TABLE_HEADER_ROWS
):
135 case XML_ELEMENT(TABLE
, XML_TABLE_ROWS
):
136 return new ScXMLExternalRefRowsContext(
137 GetScImport(), mrExternalRefInfo
);
138 case XML_ELEMENT(TABLE
, XML_TABLE_ROW
):
139 return new ScXMLExternalRefRowContext(
140 GetScImport(), pAttribList
, mrExternalRefInfo
);
142 XMLOFF_WARN_UNKNOWN_ELEMENT("sc", nElement
);
147 ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
148 ScXMLImport
& rImport
,
149 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
, ScXMLExternalTabData
& rRefInfo
) :
150 ScXMLImportContext( rImport
),
152 mrExternalRefInfo(rRefInfo
),
155 mrExternalRefInfo
.mnCol
= 0;
157 for (auto &it
: *rAttrList
)
159 switch (it
.getToken())
161 case XML_ELEMENT(TABLE
, XML_NUMBER_ROWS_REPEATED
):
163 mnRepeatRowCount
= std::max(it
.toInt32(), static_cast<sal_Int32
>(1));
170 ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
174 Reference
< XFastContextHandler
> SAL_CALL
ScXMLExternalRefRowContext::createFastChildContext(
175 sal_Int32 nElement
, const Reference
< XFastAttributeList
>& xAttrList
)
177 sax_fastparser::FastAttributeList
*pAttribList
=
178 &sax_fastparser::castToFastAttributeList( xAttrList
);
180 if (nElement
== XML_ELEMENT(TABLE
, XML_TABLE_CELL
) || nElement
== XML_ELEMENT(TABLE
, XML_COVERED_TABLE_CELL
))
181 return new ScXMLExternalRefCellContext(mrScImport
, pAttribList
, mrExternalRefInfo
);
186 void SAL_CALL
ScXMLExternalRefRowContext::endFastElement( sal_Int32
/* nElement */ )
188 ScExternalRefCache::TableTypeRef pTab
= mrExternalRefInfo
.mpCacheTable
;
190 for (sal_Int32 i
= 1; i
< mnRepeatRowCount
; ++i
)
192 // Performance: duplicates of a non-existent row will still not exist.
193 // Don't find that out for every cell.
194 // External references often are a sparse matrix.
195 if (i
== 1 && !pTab
->hasRow( mrExternalRefInfo
.mnRow
))
197 mrExternalRefInfo
.mnRow
+= mnRepeatRowCount
;
201 for (sal_Int32 j
= 0; j
< mrExternalRefInfo
.mnCol
; ++j
)
203 ScExternalRefCache::TokenRef pToken
= pTab
->getCell(
204 static_cast<SCCOL
>(j
), static_cast<SCROW
>(mrExternalRefInfo
.mnRow
));
208 pTab
->setCell(static_cast<SCCOL
>(j
),
209 static_cast<SCROW
>(mrExternalRefInfo
.mnRow
+i
), pToken
);
213 mrExternalRefInfo
.mnRow
+= mnRepeatRowCount
;
216 ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
217 ScXMLImport
& rImport
,
218 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
, ScXMLExternalTabData
& rRefInfo
) :
219 ScXMLImportContext( rImport
),
221 mrExternalRefInfo(rRefInfo
),
225 mnCellType(css::util::NumberFormat::UNDEFINED
),
229 using namespace ::xmloff::token
;
231 for (auto &it
: *rAttrList
)
233 switch ( it
.getToken() )
235 case XML_ELEMENT(TABLE
, XML_STYLE_NAME
):
237 XMLTableStylesContext
* pStyles
= static_cast<XMLTableStylesContext
*>(mrScImport
.GetAutoStyles());
238 const XMLTableStyleContext
* pStyle
= static_cast<const XMLTableStyleContext
*>(
239 pStyles
->FindStyleChildContext(XmlStyleFamily::TABLE_CELL
, it
.toString(), true));
241 mnNumberFormat
= const_cast<XMLTableStyleContext
*>(pStyle
)->GetNumberFormat();
244 case XML_ELEMENT(TABLE
, XML_NUMBER_COLUMNS_REPEATED
):
246 mnRepeatCount
= ::std::max( it
.toInt32(), static_cast<sal_Int32
>(1) );
249 case XML_ELEMENT(OFFICE
, XML_VALUE_TYPE
):
251 mnCellType
= ScXMLImport::GetCellType( it
.toCString(), it
.getLength() );
254 case XML_ELEMENT(OFFICE
, XML_VALUE
):
258 mfCellValue
= it
.toDouble();
264 case XML_ELEMENT(OFFICE
, XML_DATE_VALUE
):
266 if ( !it
.isEmpty() && mrScImport
.SetNullDateOnUnitConverter() )
268 mrScImport
.GetMM100UnitConverter().convertDateTime( mfCellValue
, it
.toView() );
274 case XML_ELEMENT(OFFICE
, XML_TIME_VALUE
):
278 ::sax::Converter::convertDuration( mfCellValue
, it
.toView() );
284 case XML_ELEMENT(OFFICE
, XML_STRING_VALUE
):
288 maCellString
= it
.toString();
294 case XML_ELEMENT(OFFICE
, XML_BOOLEAN_VALUE
):
298 mfCellValue
= IsXMLToken( it
, XML_TRUE
) ? 1.0 : 0.0;
310 ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
314 Reference
< XFastContextHandler
> SAL_CALL
ScXMLExternalRefCellContext::createFastChildContext(
315 sal_Int32 nElement
, const Reference
< XFastAttributeList
>& /*xAttrList*/ )
317 if (nElement
== XML_ELEMENT(TEXT
, XML_P
))
318 return new ScXMLExternalRefCellTextContext(mrScImport
, *this);
323 void SAL_CALL
ScXMLExternalRefCellContext::endFastElement( sal_Int32
/*nElement*/ )
325 if (!maCellString
.isEmpty())
328 for (sal_Int32 i
= 0; i
< mnRepeatCount
; ++i
, ++mrExternalRefInfo
.mnCol
)
333 ScExternalRefCache::TokenRef aToken
;
335 aToken
.reset(new formula::FormulaDoubleToken(mfCellValue
));
338 ScDocument
& rDoc
= mrScImport
.GetDoc().getDoc();
339 svl::SharedString aSS
= rDoc
.GetSharedStringPool().intern(maCellString
);
340 aToken
.reset(new formula::FormulaStringToken(std::move(aSS
)));
343 sal_uInt32 nNumFmt
= mnNumberFormat
>= 0 ? static_cast<sal_uInt32
>(mnNumberFormat
) : 0;
344 mrExternalRefInfo
.mpCacheTable
->setCell(
345 static_cast<SCCOL
>(mrExternalRefInfo
.mnCol
),
346 static_cast<SCROW
>(mrExternalRefInfo
.mnRow
),
351 void ScXMLExternalRefCellContext::SetCellString(const OUString
& rStr
)
356 ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
357 ScXMLImport
& rImport
,
358 ScXMLExternalRefCellContext
& rParent
) :
359 ScXMLImportContext( rImport
),
364 ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
368 void SAL_CALL
ScXMLExternalRefCellTextContext::characters( const OUString
& rChars
)
370 maCellStrBuf
.append( rChars
);
373 void SAL_CALL
ScXMLExternalRefCellTextContext::endFastElement( sal_Int32
/*nElement*/ )
375 mrParent
.SetCellString( maCellStrBuf
.makeStringAndClear() );
378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */