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