LibreOffice Module xmloff (master) 1
XMLNumberStyles.cxx
Go to the documentation of this file.
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
22#include <utility>
24#include <xmloff/xmlimp.hxx>
26#include <xmloff/xmltoken.hxx>
27
28#include <o3tl/string_view.hxx>
29#include <sal/log.hxx>
30
31#include "sdxmlexp_impl.hxx"
32#include "sdxmlimp_impl.hxx"
33
34using namespace ::xmloff::token;
35
36namespace {
37
38struct SdXMLDataStyleNumber
39{
40 enum XMLTokenEnum meNumberStyle;
41 bool mbLong;
42 bool mbTextual;
43 bool mbDecimal02;
44 const char* mpText;
45};
46
47}
48
49SdXMLDataStyleNumber const aSdXMLDataStyleNumbers[] =
50{
51 { XML_DAY, false, false, false, nullptr },
52 { XML_DAY, true, false, false, nullptr },
53 { XML_MONTH, true, false, false, nullptr },
54 { XML_MONTH, false, true, false, nullptr },
55 { XML_MONTH, true, true, false, nullptr },
56 { XML_YEAR, false, false, false, nullptr },
57 { XML_YEAR, true, false, false, nullptr },
58 { XML_DAY_OF_WEEK, false, false, false, nullptr },
59 { XML_DAY_OF_WEEK, true, false, false, nullptr },
60 { XML_TEXT, false, false, false, "." },
61 { XML_TEXT, false, false, false, " " },
62 { XML_TEXT, false, false, false, ", " },
63 { XML_TEXT, false, false, false, ". " },
64 { XML_HOURS, false, false, false, nullptr },
65 { XML_MINUTES, false, false, false, nullptr },
66 { XML_TEXT, false, false, false, ":" },
67 { XML_AM_PM, false, false, false, nullptr },
68 { XML_SECONDS, false, false, false, nullptr },
69 { XML_SECONDS, false, false, true, nullptr },
70 { XML_TOKEN_INVALID, false, false, false, nullptr }
71};
72
73// date
75{
76 NONE = 0,
77 Day = 1, // <number:day/>
78 DayLong = 2, // <number:day number:style="long"/>
79 MonthLong = 3, // <number:month number:style="long"/>
80 MonthText = 4, // <number:month number:textual="true"/>
81 MonthLongText = 5, // <number:month number:style="long" number:textual="true"/>
82 Year = 6, // <number:year/>
83 YearLong = 7, // <number:year number:style="long"/>
84 DayOfWeek = 8, // <number:day-of-week/>
85 DayOfWeekLong = 9, // <number:day-of-week number:style="long"/>
86 TextPoint = 10, // <number:text>.</number:text>
87 TextSpace = 11, // <number:text> </number:text>
88 TextCommaSpace = 12, // <number:text>, </number:text>
89 TextPointSpace = 13, // <number:text>. </number:text>
90 Hours = 14, // <number:hours/>
91 Minutes = 15, // <number:minutes/>
92 TextColon = 16, // <number:text>:</number:text>
93 AmPm = 17, // <number:am-pm/>
94 Seconds = 18, // <number:seconds/>
95 Seconds_02 = 19, // <number:seconds number:/>
96};
97
99{
100 const char* mpName;
104};
105
107{
108 "D1", true, true,
109 {
116 }
117};
118
120{
121 "D2", true, true,
122 {
131 }
132};
133
135{
136 "D3", false, true,
137 {
144 }
145};
146
148{
149 "D4", false, true,
150 {
157 }
158};
159
161{
162 "D5", false, true,
163 {
170 }
171};
172
174{
175 "D6", false, true,
176 {
183 }
184};
185
187{
188 "D7", false, true,
189 {
198 }
199};
200
202{
203 "D8", false, true,
204 {
213 }
214};
215
217{ "T1", true, false,
218 {
226 }
227};
228
230{ "T2", false, false,
231 {
236 }
237};
238
240{ "T3", false, false,
241 {
248 }
249};
250
252{ "T4", false, false,
253 {
260 }
261};
262
264{ "T5", false, false,
265 {
271 }
272};
273
275{ "T6", false, false,
276 {
284 }
285};
286
288{ "T7", false, false,
289 {
297 }
298};
299
301{
310};
311
313{
321};
322
323// export
324
325static void SdXMLExportDataStyleNumber( SdXMLExport& rExport, SdXMLDataStyleNumber const & rElement )
326{
327 if( rElement.mbDecimal02 )
328 {
330 }
331
332 if( rElement.mbLong )
333 {
335 }
336
337 if( rElement.mbTextual )
338 {
340 }
341
342 SvXMLElementExport aNumberStyle( rExport, XML_NAMESPACE_NUMBER, rElement.meNumberStyle, true, false );
343 if( rElement.mpText )
344 {
345 OUString sAttrValue( OUString::createFromAscii( rElement.mpText ) );
346 rExport.GetDocHandler()->characters( sAttrValue );
347 }
348}
349
350static void SdXMLExportStyle( SdXMLExport& rExport, const SdXMLFixedDataStyle* pStyle, const SdXMLFixedDataStyle* pStyle2 = nullptr )
351{
352 // name
353 OUString sAttrValue = OUString::createFromAscii( pStyle->mpName );
354 if( pStyle2 )
355 sAttrValue += OUString::createFromAscii( pStyle2->mpName );
356
357 rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_NAME, sAttrValue );
358
359 if( pStyle->mbAutomatic )
360 {
362 }
363
364 SvXMLElementExport aElement( rExport, XML_NAMESPACE_NUMBER, pStyle->mbDateStyle ? XML_DATE_STYLE : XML_TIME_STYLE, true, true );
365
366 do
367 {
368
369 const DataStyleNumber* pElements = &pStyle->mpFormat[0];
370
371 while( *pElements != DataStyleNumber::NONE )
372 {
373 SdXMLDataStyleNumber const & rElement = aSdXMLDataStyleNumbers[ static_cast<int>(*pElements++) - 1 ];
374 SdXMLExportDataStyleNumber( rExport, rElement );
375 }
376
377 if( pStyle2 )
378 {
379 SdXMLDataStyleNumber const & rElement = aSdXMLDataStyleNumbers[ static_cast<int>(DataStyleNumber::TextSpace) - 1 ];
380 SdXMLExportDataStyleNumber( rExport, rElement );
381 }
382
383 pStyle = pStyle2;
384 pStyle2 = nullptr;
385 }
386 while( pStyle );
387}
388
390{
391 SAL_WARN_IF( (nStyle < 0) || (nStyle >= SdXMLTimeFormatCount), "xmloff", "Unknown time style!" );
392 if( (nStyle >= 0) && (nStyle < SdXMLTimeFormatCount) )
393 SdXMLExportStyle( rExport, aSdXMLFixedTimeFormats[ nStyle ] );
394}
395
397{
398 if( nStyle > 0x0f )
399 {
400 int nDateStyle = nStyle & 0x0f;
401 bool bHasDate = nDateStyle != 0;
402
403 if( nDateStyle > 1 )
404 nDateStyle -= 2;
405
406 SAL_WARN_IF(nDateStyle >= SdXMLDateFormatCount, "xmloff", "unknown date style!");
407
408 int nTimeStyle = (nStyle >> 4) & 0x0f;
409 bool bHasTime = nTimeStyle != 0;
410
411 if( nTimeStyle > 1 )
412 nTimeStyle -= 2;
413
414 SAL_WARN_IF(nTimeStyle >= SdXMLTimeFormatCount, "xmloff", "Unknown time style!");
415
416 if ((nDateStyle < SdXMLDateFormatCount) && (nTimeStyle < SdXMLTimeFormatCount))
417 {
418 if( bHasDate )
419 {
420 if( bHasTime )
421 {
422 SdXMLExportStyle( rExport, aSdXMLFixedDateFormats[ nDateStyle ], aSdXMLFixedTimeFormats[ nTimeStyle ] );
423 }
424 else
425 {
426 SdXMLExportStyle( rExport, aSdXMLFixedDateFormats[ nDateStyle ] );
427 }
428 }
429 else if( bHasTime )
430 {
431 SdXMLExportStyle( rExport, aSdXMLFixedTimeFormats[ nTimeStyle ] );
432 }
433 }
434 }
435 else
436 {
437 SAL_WARN_IF( (nStyle < 0) || (nStyle >= SdXMLDateFormatCount), "xmloff", "unknown date style!" );
438 if( (nStyle >= 0) && (nStyle < SdXMLDateFormatCount) )
439 SdXMLExportStyle( rExport, aSdXMLFixedDateFormats[ nStyle ] );
440 }
441}
442
443OUString SdXMLNumberStylesExporter::getTimeStyleName(const sal_Int32 nTimeFormat )
444{
445 sal_Int32 nFormat = nTimeFormat;
446 if( nFormat > 1 )
447 nFormat -= 2;
448
449 if( (nFormat >= 0) && (nFormat < SdXMLTimeFormatCount) )
450 {
451 return OUString::createFromAscii(aSdXMLFixedTimeFormats[nFormat]->mpName );
452 }
453 else
454 {
455 return OUString();
456 }
457}
458
459OUString SdXMLNumberStylesExporter::getDateStyleName(const sal_Int32 nDateFormat )
460{
461 sal_Int32 nFormat = nDateFormat;
462
463 if( nFormat > 0x0f )
464 {
465 OUString aStr;
466 if( nFormat & 0x0f )
467 aStr = getDateStyleName( nFormat & 0x0f );
468 aStr += getTimeStyleName( (nFormat >> 4) & 0x0f );
469 return aStr;
470 }
471
472 if( nFormat > 1 )
473 nFormat -= 2;
474
475 if( (nFormat >= 0) && (nFormat < SdXMLDateFormatCount) )
476 {
477 return OUString::createFromAscii(aSdXMLFixedDateFormats[nFormat]->mpName );
478 }
479 else
480 {
481 return OUString();
482 }
483}
484
485// import
486
488{
489private:
491
493 bool mbLong;
496 OUString maText;
498
499public:
500
502 sal_Int32 nElement,
503 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
505 SvXMLImportContextRef xSlaveContext );
506
507 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
508 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
509
510 virtual void SAL_CALL startFastElement( sal_Int32 nElement,
511 const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) override;
512
513 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
514
515 virtual void SAL_CALL characters( const OUString& rChars ) override;
516};
517
518
520 SvXMLImport& rImport,
521 sal_Int32 nElement,
522 const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
524 SvXMLImportContextRef xSlaveContext )
525: SvXMLImportContext(rImport),
526 mpParent( pParent ),
527 maNumberStyle( SvXMLImport::getNameFromToken(nElement) ),
528 mxSlaveContext(std::move( xSlaveContext ))
529{
530 mbLong = false;
531 mbTextual = false;
532 mbDecimal02 = false;
533
534 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
535 {
536 switch (aIter.getToken())
537 {
539 mbDecimal02 = IsXMLToken( aIter, XML_2 );
540 break;
542 mbLong = IsXMLToken( aIter, XML_LONG );
543 break;
545 mbTextual = IsXMLToken( aIter, XML_TRUE );
546 break;
547 default:
548 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
549 }
550 }
551
552}
553
554css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLNumberFormatMemberImportContext::createFastChildContext(
555 sal_Int32 nElement,
556 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
557{
558 return mxSlaveContext->createFastChildContext( nElement, xAttrList );
559}
560
562 sal_Int32 nElement,
563 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
564{
565 mxSlaveContext->startFastElement( nElement, xAttrList );
566}
567
569{
570 mxSlaveContext->endFastElement(nElement);
571
572 if( mpParent )
574}
575
577{
578 mxSlaveContext->characters( rChars );
579 maText += rChars;
580}
581
582
583SdXMLNumberFormatImportContext::SdXMLNumberFormatImportContext( SdXMLImport& rImport, sal_Int32 nElement, SvXMLNumImpData* pNewData, SvXMLStylesTokens nNewType, const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList, SvXMLStylesContext& rStyles)
584: SvXMLNumFormatContext(rImport, nElement, pNewData, nNewType, xAttrList, rStyles),
585 mbAutomatic( false ),
586 mnElements{},
587 mnIndex(0),
588 mnKey( -1 )
589{
590 mbTimeStyle = (nElement & TOKEN_MASK) == XML_TIME_STYLE;
591
592 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
593 {
594 if( aIter.getToken() == XML_ELEMENT(NUMBER, XML_AUTOMATIC_ORDER) )
595 mbAutomatic = IsXMLToken( aIter, XML_TRUE );
596 else
597 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
598 }
599}
600
602{
603}
604
605void SdXMLNumberFormatImportContext::add( std::u16string_view rNumberStyle, bool bLong, bool bTextual, bool bDecimal02, std::u16string_view rText )
606{
607 if (mnIndex == 16)
608 return;
609
610 const SdXMLDataStyleNumber* pStyleMember = aSdXMLDataStyleNumbers;
611 for( sal_uInt8 nIndex = 0; pStyleMember->meNumberStyle != XML_TOKEN_INVALID; nIndex++, pStyleMember++ )
612 {
613 if( IsXMLToken(rNumberStyle, pStyleMember->meNumberStyle) &&
614 (pStyleMember->mbLong == bLong) &&
615 (pStyleMember->mbTextual == bTextual) &&
616 (pStyleMember->mbDecimal02 == bDecimal02) &&
617 ( ( (pStyleMember->mpText == nullptr) && (rText.empty()) ) ||
618 ( pStyleMember->mpText && (o3tl::equalsAscii( rText, pStyleMember->mpText ) ) ) ) )
619 {
620 mnElements[mnIndex++] = static_cast<DataStyleNumber>(nIndex + 1);
621 return;
622 }
623 }
624}
625
626bool SdXMLNumberFormatImportContext::compareStyle( const SdXMLFixedDataStyle* pStyle, sal_Int16& nIndex ) const
627{
628 if( (pStyle->mbAutomatic != mbAutomatic) && (nIndex == 0))
629 return false;
630
631 sal_Int16 nCompareIndex;
632 for( nCompareIndex = 0; nCompareIndex < 8; nIndex++, nCompareIndex++ )
633 {
634 if( pStyle->mpFormat[nCompareIndex] != mnElements[nIndex] )
635 return false;
636 }
637
638 return true;
639}
640
642{
643 for( ; mnIndex < 16; mnIndex++ )
644 {
646 }
647
648 if( mbTimeStyle )
649 {
650 // compare import with all time styles
651 for( sal_Int16 nFormat = 0; nFormat < SdXMLTimeFormatCount; nFormat++ )
652 {
653 sal_Int16 nIndex = 0;
655 {
656 mnKey = nFormat + 2;
657 break;
658 }
659 }
660 }
661 else
662 {
663 // compare import with all date styles
664 for( sal_Int16 nFormat = 0; nFormat < SdXMLDateFormatCount; nFormat++ )
665 {
666 sal_Int16 nIndex = 0;
668 {
669 mnKey = nFormat + 2;
670 break;
671 }
673 {
674 // if it's a valid date ending with a space, see if a time style follows
675 for( sal_Int16 nTimeFormat = 0; nTimeFormat < SdXMLTimeFormatCount; nTimeFormat++ )
676 {
677 sal_Int16 nIndex2 = nIndex + 1;
678 if( compareStyle( aSdXMLFixedTimeFormats[nTimeFormat], nIndex2 ) )
679 {
680 mnKey = (nFormat + 2) | ((nTimeFormat + 2) << 4);
681 break;
682 }
683 }
684 }
685 }
686
687 // no date style found? maybe it's an extended time style
688 if( mnKey == -1 )
689 {
690 // compare import with all time styles
691 for( sal_Int16 nFormat = 0; nFormat < SdXMLTimeFormatCount; nFormat++ )
692 {
693 sal_Int16 nIndex = 0;
695 {
696 mnKey = (nFormat + 2) << 4;
697 break;
698 }
699 }
700 }
701 }
702}
703
704css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLNumberFormatImportContext::createFastChildContext(
705 sal_Int32 nElement,
706 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
707{
708 return new SdXMLNumberFormatMemberImportContext( GetImport(), nElement, xAttrList,
709 this, static_cast<SvXMLImportContext*>(SvXMLNumFormatContext::createFastChildContext( nElement, xAttrList ).get()) );
710}
711
712/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const sal_Int16 SdXMLDateFormatCount
const sal_Int16 SdXMLTimeFormatCount
const SdXMLFixedDataStyle aSdXML_TimeStyle_1
const SdXMLFixedDataStyle aSdXML_DateStyle_6
static void SdXMLExportDataStyleNumber(SdXMLExport &rExport, SdXMLDataStyleNumber const &rElement)
const SdXMLFixedDataStyle aSdXML_TimeStyle_5
const SdXMLFixedDataStyle *const aSdXMLFixedTimeFormats[SdXMLTimeFormatCount]
const SdXMLFixedDataStyle aSdXML_TimeStyle_7
SdXMLDataStyleNumber const aSdXMLDataStyleNumbers[]
const SdXMLFixedDataStyle aSdXML_DateStyle_1
const SdXMLFixedDataStyle aSdXML_TimeStyle_2
const SdXMLFixedDataStyle aSdXML_Standard_Short
const SdXMLFixedDataStyle aSdXML_TimeStyle_3
const SdXMLFixedDataStyle aSdXML_DateStyle_4
const SdXMLFixedDataStyle aSdXML_DateStyle_2
const SdXMLFixedDataStyle aSdXML_Standard_Long
static void SdXMLExportStyle(SdXMLExport &rExport, const SdXMLFixedDataStyle *pStyle, const SdXMLFixedDataStyle *pStyle2=nullptr)
const SdXMLFixedDataStyle aSdXML_TimeStyle_6
const SdXMLFixedDataStyle aSdXML_DateStyle_5
DataStyleNumber
const SdXMLFixedDataStyle *const aSdXMLFixedDateFormats[SdXMLDateFormatCount]
const SdXMLFixedDataStyle aSdXML_TimeStyle_4
const SdXMLFixedDataStyle aSdXML_DateStyle_3
void add(std::u16string_view rNumberStyle, bool bLong, bool bTextual, bool bDecimal02, std::u16string_view rText)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
bool compareStyle(const SdXMLFixedDataStyle *pStyle, sal_Int16 &nIndex) const
SdXMLNumberFormatImportContext(SdXMLImport &rImport, sal_Int32 nElement, SvXMLNumImpData *pNewData, SvXMLStylesTokens nNewType, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, SvXMLStylesContext &rStyles)
virtual ~SdXMLNumberFormatImportContext() override
virtual void SAL_CALL characters(const OUString &rChars) override
This method is called for all characters that are contained in the current element.
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &) override
SdXMLNumberFormatMemberImportContext(SvXMLImport &rImport, sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, SdXMLNumberFormatImportContext *pParent, SvXMLImportContextRef xSlaveContext)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
SdXMLNumberFormatImportContext * mpParent
static void exportTimeStyle(SdXMLExport &rExport, sal_Int32 nStyle)
static void exportDateStyle(SdXMLExport &rExport, sal_Int32 nStyle)
static OUString getDateStyleName(const sal_Int32 nDateFormat)
static OUString getTimeStyleName(const sal_Int32 nTimeFormat)
void AddAttribute(sal_uInt16 nPrefix, const OUString &rName, const OUString &rValue)
Definition: xmlexp.cxx:907
const css::uno::Reference< css::xml::sax::XDocumentHandler > & GetDocHandler() const
Definition: xmlexp.hxx:379
This class deliberately does not support XWeak, to improve performance when loading large documents.
Definition: xmlictxt.hxx:48
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:60
friend class SvXMLImport
Definition: xmlictxt.hxx:49
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
Definition: xmlnumfi.cxx:1311
DayOfWeek
RegionData_Impl * mpParent
sal_Int32 nIndex
#define SAL_WARN_IF(condition, area, stream)
aStr
NONE
bool equalsAscii(std::u16string_view s1, std::string_view s2)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
Handling of tokens in XML:
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:50
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3597
DataStyleNumber mpFormat[8]
sal_uInt32 mnIndex
NUMBER
unsigned char sal_uInt8
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:114
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97
constexpr sal_Int32 TOKEN_MASK
Definition: xmlimp.hxx:94
constexpr sal_uInt16 XML_NAMESPACE_STYLE
constexpr sal_uInt16 XML_NAMESPACE_NUMBER
SvXMLStylesTokens
Definition: xmlnumfi.hxx:39