Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/xmloff/source/text/XMLTextMarkImportContext.cxx
Line
Count
Source
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 "XMLTextMarkImportContext.hxx"
21
22
23
#include <rtl/ustring.hxx>
24
#include <sal/log.hxx>
25
#include <osl/diagnose.h>
26
#include <sax/tools/converter.hxx>
27
#include <xmloff/xmluconv.hxx>
28
#include <xmloff/xmltoken.hxx>
29
#include <xmloff/xmlimp.hxx>
30
#include <xmloff/xmlnamespace.hxx>
31
#include <xmloff/odffields.hxx>
32
#include <xmloff/xmlement.hxx>
33
#include <com/sun/star/frame/XModel.hpp>
34
#include <com/sun/star/text/ControlCharacter.hpp>
35
#include <com/sun/star/text/XTextContent.hpp>
36
#include <com/sun/star/text/XTextRangeCompare.hpp>
37
#include <com/sun/star/beans/XPropertySet.hpp>
38
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
39
#include <com/sun/star/container/XNamed.hpp>
40
#include <com/sun/star/rdf/XMetadatable.hpp>
41
42
#include <com/sun/star/text/XFormField.hpp>
43
#include <comphelper/diagnose_ex.hxx>
44
45
#include <RDFaImportHelper.hxx>
46
47
48
using namespace ::com::sun::star;
49
using namespace ::com::sun::star::text;
50
using namespace ::com::sun::star::uno;
51
using namespace ::com::sun::star::beans;
52
using namespace ::com::sun::star::lang;
53
using namespace ::com::sun::star::container;
54
using namespace ::com::sun::star::xml::sax;
55
using namespace ::xmloff::token;
56
57
58
XMLFieldParamImportContext::XMLFieldParamImportContext(
59
    SvXMLImport& rImport,
60
    XMLTextImportHelper& rHlp ) :
61
31
        SvXMLImportContext(rImport),
62
31
        rHelper(rHlp)
63
31
{
64
31
}
65
66
67
void XMLFieldParamImportContext::startFastElement(sal_Int32 /*nElement*/, const css::uno::Reference< css::xml::sax::XFastAttributeList> & xAttrList)
68
31
{
69
31
    OUString sName;
70
31
    OUString sValue;
71
72
31
    for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
73
52
    {
74
52
        switch (aIter.getToken())
75
52
        {
76
26
            case XML_ELEMENT(FIELD, XML_NAME):
77
26
                sName = aIter.toString();
78
26
                break;
79
26
            case XML_ELEMENT(FIELD, XML_VALUE):
80
26
                sValue = aIter.toString();
81
26
                break;
82
0
            default:
83
0
                XMLOFF_WARN_UNKNOWN("xmloff", aIter);
84
52
        }
85
52
    }
86
31
    if (rHelper.hasCurrentFieldCtx() && !sName.isEmpty()) {
87
26
        rHelper.addFieldParam(sName, sValue);
88
26
    }
89
31
}
90
91
92
XMLTextMarkImportContext::XMLTextMarkImportContext(
93
    SvXMLImport& rImport,
94
    XMLTextImportHelper& rHlp,
95
    uno::Reference<uno::XInterface> & io_rxCrossRefHeadingBookmark )
96
826
    : SvXMLImportContext(rImport)
97
826
    , m_rHelper(rHlp)
98
826
    , m_rxCrossRefHeadingBookmark(io_rxCrossRefHeadingBookmark)
99
826
    , m_isHidden(false)
100
826
    , m_bHaveAbout(false)
101
826
{
102
826
}
103
104
namespace {
105
106
enum lcl_MarkType { TypeReference, TypeReferenceStart, TypeReferenceEnd,
107
                    TypeBookmark, TypeBookmarkStart, TypeBookmarkEnd,
108
                    TypeFieldmark, TypeFieldmarkStart, TypeFieldmarkSeparator, TypeFieldmarkEnd
109
                  };
110
111
}
112
113
SvXMLEnumMapEntry<lcl_MarkType> const lcl_aMarkTypeMap[] =
114
{
115
    { XML_REFERENCE_MARK,         TypeReference },
116
    { XML_REFERENCE_MARK_START,   TypeReferenceStart },
117
    { XML_REFERENCE_MARK_END,     TypeReferenceEnd },
118
    { XML_BOOKMARK,               TypeBookmark },
119
    { XML_BOOKMARK_START,         TypeBookmarkStart },
120
    { XML_BOOKMARK_END,           TypeBookmarkEnd },
121
    { XML_FIELDMARK,              TypeFieldmark },
122
    { XML_FIELDMARK_START,        TypeFieldmarkStart },
123
    { XML_FIELDMARK_SEPARATOR,    TypeFieldmarkSeparator },
124
    { XML_FIELDMARK_END,          TypeFieldmarkEnd },
125
    { XML_TOKEN_INVALID,          lcl_MarkType(0) },
126
};
127
128
129
static const OUString & lcl_getFormFieldmarkName(std::u16string_view name)
130
532
{
131
532
    if (name == ODF_FORMCHECKBOX ||
132
532
        name == u"msoffice.field.FORMCHECKBOX" ||
133
532
        name == u"ecma.office-open-xml.field.FORMCHECKBOX")
134
0
        return ODF_FORMCHECKBOX;
135
532
    else if (name == ODF_FORMDROPDOWN ||
136
532
             name == u"ecma.office-open-xml.field.FORMDROPDOWN")
137
0
        return ODF_FORMDROPDOWN;
138
532
    else
139
532
        return EMPTY_OUSTRING;
140
532
}
141
142
static OUString lcl_getFieldmarkName(OUString const& name)
143
11
{
144
11
    if (name == "msoffice.field.FORMTEXT" ||
145
11
        name == "ecma.office-open-xml.field.FORMTEXT")
146
0
        return ODF_FORMTEXT;
147
11
    else
148
11
        return name;
149
11
}
150
151
152
void XMLTextMarkImportContext::startFastElement( sal_Int32 nElement,
153
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
154
826
{
155
826
    if (!FindName(xAttrList))
156
20
    {
157
20
        m_sBookmarkName.clear();
158
20
    }
159
160
826
    if ((nElement & TOKEN_MASK) == XML_FIELDMARK_START ||
161
813
        (nElement & TOKEN_MASK) == XML_FIELDMARK)
162
13
    {
163
13
        if (m_sBookmarkName.isEmpty())
164
0
        {
165
0
            m_sBookmarkName = "Unknown";
166
0
        }
167
13
        m_rHelper.pushFieldCtx( m_sBookmarkName, m_sFieldName );
168
13
    }
169
170
826
    if ((nElement & TOKEN_MASK) == XML_BOOKMARK_START)
171
22
    {
172
22
        m_rHelper.setBookmarkAttributes(m_sBookmarkName, m_isHidden, m_sCondition);
173
22
    }
174
826
}
175
176
static auto InsertFieldmark(SvXMLImport & rImport,
177
        XMLTextImportHelper & rHelper, bool const isFieldmarkSeparatorMissing) -> void
178
11
{
179
11
    assert(rHelper.hasCurrentFieldCtx()); // was set up in StartElement()
180
181
    // fdo#86795 check if it's actually a checkbox first
182
11
    auto const [ name, type ] = rHelper.getCurrentFieldType();
183
11
    OUString const fieldmarkTypeName = lcl_getFieldmarkName(type);
184
11
    if (fieldmarkTypeName == ODF_FORMCHECKBOX ||
185
11
        fieldmarkTypeName == ODF_FORMDROPDOWN)
186
0
    {   // sw can't handle checkbox with start+end
187
0
        SAL_INFO("xmloff.text", "invalid fieldmark-start/fieldmark-end ignored");
188
0
        return;
189
0
    }
190
191
11
    uno::Reference<text::XTextRange> const xStartRange(rHelper.getCurrentFieldStart());
192
11
    uno::Reference<text::XTextCursor> const xCursor(
193
11
        rHelper.GetText()->createTextCursorByRange(xStartRange));
194
11
    uno::Reference<text::XTextRangeCompare> const xCompare(rHelper.GetText(), uno::UNO_QUERY);
195
11
    if (xCompare->compareRegionStarts(xStartRange, rHelper.GetCursorAsRange()) < 0)
196
0
    {
197
0
        SAL_WARN("xmloff.text", "invalid field mark positions");
198
0
        assert(false);
199
0
    }
200
11
    xCursor->gotoRange(rHelper.GetCursorAsRange(), true);
201
202
11
    Reference<XTextContent> const xContent = XMLTextMarkImportContext::CreateAndInsertMark(
203
11
            rImport, u"com.sun.star.text.Fieldmark"_ustr, name, xCursor,
204
11
            OUString(), isFieldmarkSeparatorMissing);
205
206
11
    if (!xContent.is())
207
0
        return;
208
209
    // setup fieldmark...
210
11
    Reference<text::XFormField> const xFormField(xContent, UNO_QUERY);
211
11
    assert(xFormField.is());
212
11
    try {
213
11
        xFormField->setFieldType(fieldmarkTypeName);
214
11
    } catch (uno::RuntimeException const&) {
215
        // tdf#140437 somehow old documents had the field code in the type
216
        // attribute instead of field:param
217
1
        SAL_INFO("xmloff.text", "invalid fieldmark type, converting to param");
218
        // add without checking: FieldParamImporter::Import() catches ElementExistException
219
1
        rHelper.addFieldParam(ODF_CODE_PARAM, fieldmarkTypeName);
220
1
        xFormField->setFieldType(ODF_UNHANDLED);
221
1
    }
222
11
    rHelper.setCurrentFieldParamsTo(xFormField);
223
    // move cursor after setFieldType as that may delete/re-insert
224
11
    rHelper.GetCursor()->gotoRange(xContent->getAnchor()->getEnd(), false);
225
11
    rHelper.GetCursor()->goLeft(1, false); // move before CH_TXT_ATR_FIELDEND
226
    // tdf#129520: AppendTextNode() ignores the content index!
227
    // plan B: insert a spurious paragraph break now and join
228
    //         it in PopFieldmark()!
229
11
    rHelper.GetText()->insertControlCharacter(rHelper.GetCursor(),
230
11
            text::ControlCharacter::PARAGRAPH_BREAK, false);
231
11
    rHelper.GetCursor()->goLeft(1, false); // back to previous paragraph
232
11
}
233
234
static auto PopFieldmark(XMLTextImportHelper & rHelper) -> void
235
11
{
236
    // can't verify name because it's not written as an attribute...
237
11
    uno::Reference<text::XTextContent> const xField(rHelper.popFieldCtx(),
238
11
            uno::UNO_QUERY);
239
11
    if (!xField.is())
240
0
        return;
241
242
11
    if (rHelper.GetText() == xField->getAnchor()->getText())
243
11
    {
244
11
        try
245
11
        {   // skip CH_TXT_ATR_FIELDEND
246
11
            rHelper.GetCursor()->goRight(1, true);
247
11
            rHelper.GetCursor()->setString(OUString()); // undo AppendTextNode from InsertFieldmark
248
11
            rHelper.GetCursor()->gotoRange(xField->getAnchor()->getEnd(), false);
249
11
        }
250
11
        catch (uno::Exception const&)
251
11
        {
252
0
            assert(false); // must succeed
253
0
        }
254
11
    }
255
0
    else
256
0
    {
257
0
        SAL_INFO("xmloff.text", "fieldmark has invalid positions");
258
        // could either dispose it or leave it to end at the end of the document?
259
0
        xField->dispose();
260
0
    }
261
11
}
262
263
void XMLTextMarkImportContext::endFastElement(sal_Int32 nElement)
264
823
{
265
823
    static constexpr OUString sAPI_bookmark = u"com.sun.star.text.Bookmark"_ustr;
266
267
823
    lcl_MarkType nTmp{};
268
823
    if (!SvXMLUnitConverter::convertEnum(nTmp, SvXMLImport::getNameFromToken(nElement), lcl_aMarkTypeMap))
269
0
        return;
270
271
823
    if (m_sBookmarkName.isEmpty() && TypeFieldmarkEnd != nTmp && TypeFieldmarkSeparator != nTmp)
272
6
        return;
273
274
817
    switch (nTmp)
275
817
    {
276
0
        case TypeReference:
277
            // export point reference mark
278
0
            CreateAndInsertMark(GetImport(),
279
0
                u"com.sun.star.text.ReferenceMark"_ustr,
280
0
                m_sBookmarkName,
281
0
                m_rHelper.GetCursorAsRange()->getStart());
282
0
            break;
283
284
532
        case TypeBookmark:
285
532
            {
286
                // tdf#94804: detect duplicate heading cross reference bookmarks
287
532
                if (m_sBookmarkName.startsWith("__RefHeading__"))
288
0
                {
289
0
                    if (m_rxCrossRefHeadingBookmark.is())
290
0
                    {
291
0
                        uno::Reference<container::XNamed> const xNamed(
292
0
                            m_rxCrossRefHeadingBookmark, uno::UNO_QUERY);
293
0
                        m_rHelper.AddCrossRefHeadingMapping(
294
0
                            m_sBookmarkName, xNamed->getName());
295
0
                        break; // don't insert
296
0
                    }
297
0
                }
298
532
            }
299
532
            [[fallthrough]];
300
532
        case TypeFieldmark:
301
532
            {
302
532
                const OUString formFieldmarkName=lcl_getFormFieldmarkName(m_sFieldName);
303
532
                bool bImportAsField = (nTmp==TypeFieldmark && !formFieldmarkName.isEmpty()); //@TODO handle abbreviation cases...
304
                // export point bookmark
305
532
                const Reference<XInterface> xContent(
306
532
                    CreateAndInsertMark(GetImport(),
307
532
                                (bImportAsField ? u"com.sun.star.text.FormFieldmark"_ustr : sAPI_bookmark),
308
532
                        m_sBookmarkName,
309
532
                        m_rHelper.GetCursorAsRange()->getStart(),
310
532
                        m_sXmlId) );
311
532
                if (nTmp==TypeFieldmark) {
312
0
                    if (xContent.is() && bImportAsField) {
313
                        // setup fieldmark...
314
0
                        Reference< css::text::XFormField> xFormField(xContent, UNO_QUERY);
315
0
                        xFormField->setFieldType(formFieldmarkName);
316
0
                        if (xFormField.is() && m_rHelper.hasCurrentFieldCtx()) {
317
0
                            m_rHelper.setCurrentFieldParamsTo(xFormField);
318
0
                        }
319
0
                    }
320
0
                    m_rHelper.popFieldCtx();
321
0
                }
322
532
                if (TypeBookmark == nTmp
323
532
                    && m_sBookmarkName.startsWith("__RefHeading__"))
324
0
                {
325
0
                    assert(xContent.is());
326
0
                    m_rxCrossRefHeadingBookmark = xContent;
327
0
                }
328
532
            }
329
532
            break;
330
331
22
        case TypeBookmarkStart:
332
            // save XTextRange for later construction of bookmark
333
22
            {
334
22
                std::shared_ptr< ::xmloff::ParsedRDFaAttributes >
335
22
                    xRDFaAttributes;
336
22
                if (m_bHaveAbout && TypeBookmarkStart == nTmp)
337
0
                {
338
0
                    xRDFaAttributes =
339
0
                        GetImport().GetRDFaImportHelper().ParseRDFa(
340
0
                            m_sAbout, m_sProperty,
341
0
                            m_sContent, m_sDatatype);
342
0
                }
343
22
                m_rHelper.InsertBookmarkStartRange(
344
22
                    m_sBookmarkName,
345
22
                    m_rHelper.GetCursorAsRange()->getStart(),
346
22
                    m_sXmlId, xRDFaAttributes);
347
22
            }
348
22
            break;
349
350
239
        case TypeBookmarkEnd:
351
239
        {
352
            // tdf#94804: detect duplicate heading cross reference bookmarks
353
239
            if (m_sBookmarkName.startsWith("__RefHeading__"))
354
0
            {
355
0
                if (m_rxCrossRefHeadingBookmark.is())
356
0
                {
357
0
                    uno::Reference<container::XNamed> const xNamed(
358
0
                        m_rxCrossRefHeadingBookmark, uno::UNO_QUERY);
359
0
                    m_rHelper.AddCrossRefHeadingMapping(
360
0
                        m_sBookmarkName, xNamed->getName());
361
0
                    break; // don't insert
362
0
                }
363
0
            }
364
365
            // get old range, and construct
366
239
            Reference<XTextRange> xStartRange;
367
239
            std::shared_ptr< ::xmloff::ParsedRDFaAttributes >
368
239
                xRDFaAttributes;
369
239
            if (m_rHelper.FindAndRemoveBookmarkStartRange(
370
239
                    m_sBookmarkName, xStartRange,
371
239
                    m_sXmlId, xRDFaAttributes))
372
21
            {
373
21
                Reference<XTextRange> xEndRange(
374
21
                    m_rHelper.GetCursorAsRange()->getStart());
375
376
                // check if beginning and end are in same XText
377
21
                if (xStartRange.is() && xEndRange.is() && xStartRange->getText() == xEndRange->getText())
378
21
                {
379
                    // create range for insertion
380
21
                    Reference<XTextCursor> xInsertionCursor =
381
21
                        m_rHelper.GetText()->createTextCursorByRange(
382
21
                            xEndRange);
383
21
                    try {
384
21
                        xInsertionCursor->gotoRange(xStartRange, true);
385
21
                    } catch (uno::Exception&) {
386
0
                        TOOLS_WARN_EXCEPTION("xmloff.text",
387
0
                            "cannot go to end position of bookmark");
388
0
                    }
389
390
                    //DBG_ASSERT(! xInsertionCursor->isCollapsed(),
391
                    //              "we want no point mark");
392
                    // can't assert, because someone could
393
                    // create a file with subsequence
394
                    // start/end elements
395
396
21
                    Reference<XInterface> xContent;
397
                    // insert reference
398
21
                    xContent = CreateAndInsertMark(GetImport(),
399
21
                            sAPI_bookmark,
400
21
                            m_sBookmarkName,
401
21
                            xInsertionCursor,
402
21
                            m_sXmlId);
403
21
                    if (xRDFaAttributes)
404
0
                    {
405
0
                        const Reference<rdf::XMetadatable>
406
0
                            xMeta(xContent, UNO_QUERY);
407
0
                        GetImport().GetRDFaImportHelper().AddRDFa(
408
0
                            xMeta, xRDFaAttributes);
409
0
                    }
410
21
                    const Reference<XPropertySet> xPropertySet(xContent, UNO_QUERY);
411
21
                    if (xPropertySet.is())
412
21
                    {
413
21
                        xPropertySet->setPropertyValue(u"BookmarkHidden"_ustr,    uno::Any(m_rHelper.getBookmarkHidden(m_sBookmarkName)));
414
21
                        xPropertySet->setPropertyValue(u"BookmarkCondition"_ustr, uno::Any(m_rHelper.getBookmarkCondition(m_sBookmarkName)));
415
21
                    }
416
21
                    if (m_sBookmarkName.startsWith("__RefHeading__"))
417
0
                    {
418
0
                        assert(xContent.is());
419
0
                        m_rxCrossRefHeadingBookmark = std::move(xContent);
420
0
                    }
421
21
                }
422
                // else: beginning/end in different XText -> ignore!
423
21
            }
424
            // else: no start found -> ignore!
425
239
            break;
426
239
        }
427
239
        case TypeFieldmarkStart:
428
13
        {
429
13
            break;
430
239
        }
431
0
        case TypeFieldmarkSeparator:
432
0
        {
433
0
            InsertFieldmark(GetImport(), m_rHelper, false);
434
0
            break;
435
239
        }
436
11
        case TypeFieldmarkEnd:
437
11
        {
438
11
            if (m_rHelper.hasCurrentFieldCtx() && !m_rHelper.hasCurrentFieldSeparator())
439
11
            {   // backward compat for old files without separator
440
11
                InsertFieldmark(GetImport(), m_rHelper, true);
441
11
            }
442
11
            PopFieldmark(m_rHelper);
443
11
            break;
444
239
        }
445
0
        case TypeReferenceStart:
446
0
        case TypeReferenceEnd:
447
0
            OSL_FAIL("reference start/end are handled in txtparai !");
448
0
            break;
449
450
0
        default:
451
0
            OSL_FAIL("unknown mark type");
452
0
            break;
453
817
    }
454
817
}
455
456
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextMarkImportContext::createFastChildContext(
457
    sal_Int32 ,
458
    const css::uno::Reference< css::xml::sax::XFastAttributeList >&  )
459
31
{
460
31
    return new XMLFieldParamImportContext(GetImport(), m_rHelper);
461
31
}
462
463
464
Reference<XTextContent> XMLTextMarkImportContext::CreateAndInsertMark(
465
    SvXMLImport& rImport,
466
    const OUString& sServiceName,
467
    const OUString& sMarkName,
468
    const Reference<XTextRange> & rRange,
469
    const OUString& i_rXmlId,
470
    bool const isFieldmarkSeparatorMissing)
471
569
{
472
    // create mark
473
569
    const Reference<XMultiServiceFactory> xFactory(rImport.GetModel(),
474
569
        UNO_QUERY);
475
569
    Reference<XInterface> xIfc;
476
477
569
    if (xFactory.is())
478
569
    {
479
569
        xIfc = xFactory->createInstance(sServiceName);
480
481
569
        if (!xIfc.is())
482
0
        {
483
0
            OSL_FAIL("CreateAndInsertMark: cannot create service?");
484
0
            return nullptr;
485
0
        }
486
487
        // set name (unless there is no name (text:meta))
488
569
        const Reference<XNamed> xNamed(xIfc, UNO_QUERY);
489
569
        if (xNamed.is())
490
569
        {
491
569
            xNamed->setName(sMarkName);
492
569
        }
493
0
        else
494
0
        {
495
0
            if (!sMarkName.isEmpty())
496
0
            {
497
0
                OSL_FAIL("name given, but XNamed not supported?");
498
0
                return nullptr;
499
0
            }
500
0
        }
501
502
569
        if (isFieldmarkSeparatorMissing)
503
11
        {
504
11
            uno::Reference<beans::XPropertySet> const xProps(xIfc, uno::UNO_QUERY_THROW);
505
11
            xProps->setPropertyValue(u"PrivateSeparatorAtStart"_ustr, uno::Any(true));
506
11
        }
507
508
        // cast to XTextContent and attach to document
509
569
        const Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
510
569
        if (xTextContent.is())
511
569
        {
512
569
            try
513
569
            {
514
                // if inserting marks, bAbsorb==sal_False will cause
515
                // collapsing of the given XTextRange.
516
569
                rImport.GetTextImport()->GetText()->insertTextContent(rRange,
517
569
                    xTextContent, true);
518
519
                // xml:id for RDF metadata -- after insertion!
520
569
                rImport.SetXmlId(xIfc, i_rXmlId);
521
522
569
                return xTextContent;
523
569
            }
524
569
            catch (css::lang::IllegalArgumentException &)
525
569
            {
526
0
                OSL_FAIL("CreateAndInsertMark: cannot insert?");
527
0
                return nullptr;
528
0
            }
529
569
        }
530
569
    }
531
0
    return nullptr;
532
569
}
533
534
bool XMLTextMarkImportContext::FindName(
535
    const Reference<XFastAttributeList> & xAttrList)
536
826
{
537
826
    bool bNameOK = false;
538
539
    // find name attribute first
540
826
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
541
821
    {
542
821
        OUString sValue = aIter.toString();
543
821
        switch(aIter.getToken())
544
821
        {
545
806
            case XML_ELEMENT(TEXT, XML_NAME):
546
806
                m_sBookmarkName = sValue;
547
806
                bNameOK = true;
548
806
                break;
549
0
            case XML_ELEMENT(XML, XML_ID):
550
0
                m_sXmlId = sValue;
551
0
                break;
552
            // RDFa
553
0
            case XML_ELEMENT(XHTML, XML_ABOUT):
554
0
                m_sAbout = sValue;
555
0
                m_bHaveAbout = true;
556
0
                break;
557
0
            case XML_ELEMENT(XHTML, XML_PROPERTY):
558
0
                m_sProperty = sValue;
559
0
                break;
560
0
            case XML_ELEMENT(XHTML, XML_CONTENT):
561
0
                m_sContent = sValue;
562
0
                break;
563
0
            case XML_ELEMENT(XHTML, XML_DATATYPE):
564
0
                m_sDatatype = sValue;
565
0
                break;
566
13
            case XML_ELEMENT(FIELD, XML_TYPE):
567
13
                m_sFieldName = sValue;
568
13
                break;
569
0
            case XML_ELEMENT(LO_EXT, XML_HIDDEN):
570
0
                ::sax::Converter::convertBool(m_isHidden, sValue);
571
0
                break;
572
0
            case XML_ELEMENT(LO_EXT, XML_CONDITION):
573
0
                m_sCondition = sValue;
574
0
                break;
575
2
            default:
576
2
                XMLOFF_WARN_UNKNOWN("xmloff", aIter);
577
821
        }
578
821
    }
579
580
826
    return bNameOK;
581
826
}
582
583
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */