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"
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
),
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
))
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
);
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));
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 '..'
122 else if (i
== 2 && c
!= '/')
123 // a '/' path separator must follow
129 void ScXMLExternalRefTabSourceContext::EndElement()
131 ScDocument
* pDoc
= mrScImport
.GetDocument();
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
),
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
);
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
);
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
),
191 mrExternalRefInfo(rRefInfo
),
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));
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
;
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
));
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
),
268 mrExternalRefInfo(rRefInfo
),
272 mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED
),
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
)
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
);
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));
297 mnNumberFormat
= const_cast<XMLTableStyleContext
*>(pStyle
)->GetNumberFormat();
300 case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED
:
302 mnRepeatCount
= ::std::max(sValue
.toInt32(), static_cast<sal_Int32
>(1));
305 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE
:
307 mnCellType
= mrScImport
.GetCellType(sValue
);
310 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE
:
312 if (sValue
.getLength())
314 mrScImport
.GetMM100UnitConverter().convertDouble(mfCellValue
, sValue
);
320 case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE
:
322 if (sValue
.getLength() && mrScImport
.SetNullDateOnUnitConverter())
324 mrScImport
.GetMM100UnitConverter().convertDateTime(mfCellValue
, sValue
);
330 case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE
:
332 if (sValue
.getLength())
334 mrScImport
.GetMM100UnitConverter().convertTime(mfCellValue
, sValue
);
340 case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE
:
342 if (sValue
.getLength())
344 maCellString
= sValue
;
350 case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE
:
352 if (sValue
.getLength())
354 mfCellValue
= IsXMLToken(sValue
, XML_TRUE
) ? 1.0 : 0.0;
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())
386 for (sal_Int32 i
= 0; i
< mnRepeatCount
; ++i
, ++mrExternalRefInfo
.mnCol
)
391 ScExternalRefCache::TokenRef aToken
;
393 aToken
.reset(new formula::FormulaDoubleToken(mfCellValue
));
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
),
405 // ============================================================================
407 ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
408 ScXMLImport
& rImport
, USHORT nPrefix
, const OUString
& rLName
,
409 const Reference
<XAttributeList
>& /*xAttrList*/, OUString
& rCellString
) :
410 SvXMLImportContext( rImport
, nPrefix
, rLName
),
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()