Coverage Report

Created: 2026-06-13 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xerces-c/src/xercesc/dom/impl/DOMLSSerializerImpl.cpp
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
/*
19
 * $Id: DOMLSSerializerImpl.cpp 1824086 2018-02-13 00:54:01Z scantor $
20
 */
21
22
#include "DOMLSSerializerImpl.hpp"
23
#include "DOMLSOutputImpl.hpp"
24
#include "DOMErrorImpl.hpp"
25
#include "DOMLocatorImpl.hpp"
26
#include "DOMImplementationImpl.hpp"
27
#include "DOMStringListImpl.hpp"
28
29
#include <xercesc/framework/MemBufFormatTarget.hpp>
30
#include <xercesc/framework/LocalFileFormatTarget.hpp>
31
32
#include <xercesc/util/TransService.hpp>
33
#include <xercesc/util/TranscodingException.hpp>
34
#include <xercesc/util/Janitor.hpp>
35
#include <xercesc/util/XMLString.hpp>
36
#include <xercesc/util/XMLUniDefs.hpp>
37
#include <xercesc/util/XMLMsgLoader.hpp>
38
#include <xercesc/dom/StDOMNode.hpp>
39
#include <xercesc/util/OutOfMemoryException.hpp>
40
#include <xercesc/util/XMLChar.hpp>
41
42
XERCES_CPP_NAMESPACE_BEGIN
43
44
45
// ---------------------------------------------------------------------------
46
//  Local const data
47
//
48
// ---------------------------------------------------------------------------
49
50
static const int INVALID_FEATURE_ID               = -1;
51
static const int CANONICAL_FORM_ID                = 0x0;
52
static const int DISCARD_DEFAULT_CONTENT_ID       = 0x1;
53
static const int ENTITIES_ID                      = 0x2;
54
static const int FORMAT_PRETTY_PRINT_ID           = 0x3;
55
static const int NORMALIZE_CHARACTERS_ID          = 0x4;
56
static const int SPLIT_CDATA_SECTIONS_ID          = 0x5;
57
static const int VALIDATION_ID                    = 0x6;
58
static const int WHITESPACE_IN_ELEMENT_CONTENT_ID = 0x7;
59
static const int BYTE_ORDER_MARK_ID               = 0x8;
60
static const int XML_DECLARATION                  = 0x9;
61
static const int FORMAT_PRETTY_PRINT_1ST_LEVEL_ID = 0xA;
62
63
//    feature                      true                       false
64
// ================================================================================
65
//canonical-form                 [optional] Not Supported     [required] (default)
66
//discard-default-content        [required] (default)         [required]
67
//entity                         [required] (default)         [optional]
68
//format-pretty-print            [optional] Partially Supported [required] (default)
69
//normalize-characters           [optional] Not Supported     [required] (default)
70
//split-cdata-sections           [required] (default)         [required]
71
//validation                     [optional] Not Supported     [required] (default)
72
//whitespace-in-element-content  [requierd] (default)         [optional] Not Supported
73
//
74
75
//
76
// Each feature has 2 entries in this array,
77
// the first for "true",
78
// the second for "false".
79
//
80
static const bool  featuresSupported[] = {
81
    false, true,  // canonical-form
82
    true,  true,  // discard-default-content
83
    true,  true,  // entity
84
    true,  true,  // format-pretty-print
85
    false, true,  // normalize-characters
86
    true,  true,  // split-cdata-sections
87
    false, true,  // validation
88
    true,  false, // whitespace-in-element-content
89
    true,  true,  // http://apache.org/xml/features/dom/byte-order-mark
90
    true,  true,  // xml-declaration
91
    true,  true   // http://apache.org/xml/features/pretty-print/space-first-level-elements
92
};
93
94
// default end-of-line sequence
95
static const XMLCh  gEOLSeq[] =
96
{
97
    chLF, chNull
98
};
99
100
//UTF-8
101
static const XMLCh  gUTF8[] =
102
{
103
    chLatin_U, chLatin_T, chLatin_F, chDash, chDigit_8, chNull
104
};
105
106
//</
107
static const XMLCh  gEndElement[] =
108
{
109
    chOpenAngle, chForwardSlash, chNull
110
};
111
112
//?>
113
static const XMLCh  gEndPI[] =
114
{
115
    chQuestion, chCloseAngle, chNull
116
};
117
118
//<?
119
static const XMLCh  gStartPI[] =
120
{
121
    chOpenAngle, chQuestion, chNull
122
};
123
124
//<?xml version="
125
static const XMLCh  gXMLDecl_VersionInfo[] =
126
{
127
    chOpenAngle, chQuestion, chLatin_x,     chLatin_m,  chLatin_l,  chSpace,
128
    chLatin_v,   chLatin_e,  chLatin_r,     chLatin_s,  chLatin_i,  chLatin_o,
129
    chLatin_n,   chEqual,    chDoubleQuote, chNull
130
};
131
132
//encoding="
133
static const XMLCh  gXMLDecl_EncodingDecl[] =
134
{
135
    chLatin_e,  chLatin_n,  chLatin_c,  chLatin_o,      chLatin_d, chLatin_i,
136
    chLatin_n,  chLatin_g,  chEqual,    chDoubleQuote,  chNull
137
};
138
139
//" standalone="
140
static const XMLCh  gXMLDecl_SDDecl[] =
141
{
142
    chLatin_s, chLatin_t, chLatin_a,   chLatin_n,    chLatin_d,   chLatin_a,
143
    chLatin_l, chLatin_o, chLatin_n,   chLatin_e,    chEqual,     chDoubleQuote,
144
    chNull
145
};
146
147
//"
148
static const XMLCh  gXMLDecl_separator[] =
149
{
150
    chDoubleQuote, chSpace, chNull
151
};
152
153
//?>
154
static const XMLCh  gXMLDecl_endtag[] =
155
{
156
    chQuestion, chCloseAngle,  chNull
157
};
158
159
//<![CDATA[
160
static const XMLCh  gStartCDATA[] =
161
{
162
    chOpenAngle, chBang,    chOpenSquare, chLatin_C, chLatin_D,
163
    chLatin_A,   chLatin_T, chLatin_A,    chOpenSquare, chNull
164
};
165
166
//]]>
167
static const XMLCh  gEndCDATA[] =
168
{
169
//    chCloseSquare, chCloseAngle, chCloseAngle, chNull  // test only: ]>>
170
      chCloseSquare, chCloseSquare, chCloseAngle, chNull
171
};
172
173
//<!--
174
static const XMLCh  gStartComment[] =
175
{
176
    chOpenAngle, chBang, chDash, chDash, chNull
177
};
178
179
//-->
180
static const XMLCh  gEndComment[] =
181
{
182
    chDash, chDash, chCloseAngle, chNull
183
};
184
185
//<!DOCTYPE
186
static const XMLCh  gStartDoctype[] =
187
{
188
    chOpenAngle, chBang,    chLatin_D, chLatin_O, chLatin_C, chLatin_T,
189
    chLatin_Y,   chLatin_P, chLatin_E, chSpace,   chNull
190
};
191
192
//PUBLIC "
193
static const XMLCh  gPublic[] =
194
{
195
    chLatin_P, chLatin_U, chLatin_B,     chLatin_L, chLatin_I,
196
    chLatin_C, chSpace,   chDoubleQuote, chNull
197
};
198
199
//SYSTEM "
200
static const XMLCh  gSystem[] =
201
{
202
    chLatin_S, chLatin_Y, chLatin_S,     chLatin_T, chLatin_E,
203
    chLatin_M, chSpace,   chDoubleQuote, chNull
204
};
205
206
//<!ENTITY
207
static const XMLCh  gStartEntity[] =
208
{
209
    chOpenAngle, chBang,    chLatin_E, chLatin_N, chLatin_T, chLatin_I,
210
    chLatin_T,   chLatin_Y, chSpace,   chNull
211
};
212
213
//NDATA "
214
static const XMLCh  gNotation[] =
215
{
216
    chLatin_N, chLatin_D,     chLatin_A, chLatin_T, chLatin_A,
217
    chSpace,   chDoubleQuote, chNull
218
};
219
220
static const XMLByte  BOM_utf8[]    = {(XMLByte)0xEF, (XMLByte)0xBB, (XMLByte)0xBF, (XMLByte) 0};
221
static const XMLByte  BOM_utf16be[] = {(XMLByte)0xFE, (XMLByte)0xFF, (XMLByte) 0};
222
static const XMLByte  BOM_utf16le[] = {(XMLByte)0xFF, (XMLByte)0xFE, (XMLByte) 0};
223
static const XMLByte  BOM_ucs4be[]  = {(XMLByte)0x00, (XMLByte)0x00, (XMLByte)0xFE, (XMLByte)0xFF, (XMLByte) 0};
224
static const XMLByte  BOM_ucs4le[]  = {(XMLByte)0xFF, (XMLByte)0xFE, (XMLByte)0x00, (XMLByte)0x00, (XMLByte) 0};
225
226
//
227
// Notification of the error though error handler
228
//
229
// The application may instruct the engine to abort serialization
230
// by returning "false".
231
//
232
// REVISIT: update the locator ctor once the line#, col#, uri and offset
233
// are available from DOM3 core
234
//
235
// REVISIT: use throwing exception to abort serialization is an interesting
236
// thing here, since the serializer is a recusive function, we
237
// can't use return, obviously. However we may have multiple try/catch
238
// along its way going back to write(). So far we don't come up with a
239
// "short-cut" to go "directly" back.
240
//
241
0
#define  TRY_CATCH_THROW(action)                                     \
242
0
fFormatter->setUnRepFlags(XMLFormatter::UnRep_Fail);                 \
243
0
try                                                                  \
244
0
{                                                                    \
245
0
    action;                                                          \
246
0
}                                                                    \
247
0
catch(TranscodingException const &e)                                 \
248
0
{                                                                    \
249
0
    reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, e.getMessage());  \
250
0
    throw e;                                                         \
251
0
}
252
253
DOMLSSerializerImpl::~DOMLSSerializerImpl()
254
0
{
255
0
    fMemoryManager->deallocate(fNewLine);//delete [] fNewLine;
256
0
    delete fNamespaceStack;
257
0
    delete fSupportedParameters;
258
    // we don't own/adopt error handler and filter
259
0
}
260
261
DOMLSSerializerImpl::DOMLSSerializerImpl(MemoryManager* const manager)
262
0
:fFeatures(0)
263
0
,fNewLine(0)
264
0
,fErrorHandler(0)
265
0
,fFilter(0)
266
0
,fDocumentVersion(XMLUni::fgVersion1_0)
267
0
,fSupportedParameters(0)
268
0
,fEncodingUsed(0)
269
0
,fNewLineUsed(0)
270
0
,fFormatter(0)
271
0
,fErrorCount(0)
272
0
,fCurrentLine(0)
273
0
,fLineFeedInTextNodePrinted(false)
274
0
,fLastWhiteSpaceInTextNode(0)
275
0
,fIsXml11(false)
276
0
,fNamespaceStack(0)
277
0
,fMemoryManager(manager)
278
0
{
279
0
    fNamespaceStack=new (fMemoryManager) RefVectorOf< RefHashTableOf<XMLCh> >(1,true, fMemoryManager);
280
281
    //
282
    // set features to default setting
283
    //
284
0
    setFeature(CANONICAL_FORM_ID,                false);
285
0
    setFeature(DISCARD_DEFAULT_CONTENT_ID,       true );
286
0
    setFeature(ENTITIES_ID,                      true );
287
0
    setFeature(FORMAT_PRETTY_PRINT_ID,           false);
288
0
    setFeature(NORMALIZE_CHARACTERS_ID,          false);
289
0
    setFeature(SPLIT_CDATA_SECTIONS_ID,          true );
290
0
    setFeature(VALIDATION_ID,                    false);
291
0
    setFeature(WHITESPACE_IN_ELEMENT_CONTENT_ID, true );
292
0
    setFeature(BYTE_ORDER_MARK_ID,               false);
293
0
    setFeature(XML_DECLARATION,                  true );
294
0
    setFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID, true );
295
296
0
    fSupportedParameters=new (fMemoryManager) DOMStringListImpl(12, fMemoryManager);
297
0
    fSupportedParameters->add(XMLUni::fgDOMErrorHandler);
298
0
    fSupportedParameters->add(XMLUni::fgDOMWRTCanonicalForm);
299
0
    fSupportedParameters->add(XMLUni::fgDOMWRTDiscardDefaultContent);
300
0
    fSupportedParameters->add(XMLUni::fgDOMWRTEntities);
301
0
    fSupportedParameters->add(XMLUni::fgDOMWRTFormatPrettyPrint);
302
0
    fSupportedParameters->add(XMLUni::fgDOMWRTNormalizeCharacters);
303
0
    fSupportedParameters->add(XMLUni::fgDOMWRTSplitCdataSections);
304
0
    fSupportedParameters->add(XMLUni::fgDOMWRTValidation);
305
0
    fSupportedParameters->add(XMLUni::fgDOMWRTWhitespaceInElementContent);
306
0
    fSupportedParameters->add(XMLUni::fgDOMWRTBOM);
307
0
    fSupportedParameters->add(XMLUni::fgDOMXMLDeclaration);
308
0
    fSupportedParameters->add(XMLUni::fgDOMWRTXercesPrettyPrint);
309
0
}
310
311
bool DOMLSSerializerImpl::canSetParameter(const XMLCh* featName
312
                                        , const void*  /*value*/) const
313
0
{
314
0
    if(XMLString::compareIStringASCII(featName, XMLUni::fgDOMErrorHandler)==0)
315
0
        return true;
316
0
    return false;
317
0
}
318
319
bool DOMLSSerializerImpl::canSetParameter(const XMLCh* featName
320
                                        , bool         state) const
321
0
{
322
0
    int featureId = INVALID_FEATURE_ID;
323
0
    return checkFeature(featName, false, featureId) ? canSetFeature(featureId, state) : false;
324
0
}
325
326
void DOMLSSerializerImpl::setParameter(const XMLCh* featName
327
                                     , const void*  value)
328
0
{
329
0
    if(XMLString::compareIStringASCII(featName, XMLUni::fgDOMErrorHandler)==0)
330
0
        fErrorHandler = (DOMErrorHandler*)value;
331
0
    else
332
0
        throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, fMemoryManager);
333
0
}
334
335
void DOMLSSerializerImpl::setParameter(const XMLCh* featName
336
                                     , bool         state)
337
0
{
338
0
    int featureId = INVALID_FEATURE_ID;
339
0
    checkFeature(featName, true, featureId);
340
341
0
    if (!canSetFeature(featureId, state))
342
0
        throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, fMemoryManager);
343
344
0
    setFeature(featureId, state);
345
346
    //
347
    // setting "canonical-form" to true will set the parameters "format-pretty-print",
348
    // "discard-default-content", and "xml-declaration", to false
349
    //
350
0
    if ((featureId == CANONICAL_FORM_ID) && state)
351
0
    {
352
0
        setFeature(FORMAT_PRETTY_PRINT_ID, false);
353
0
        setFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID, false);
354
0
        setFeature(DISCARD_DEFAULT_CONTENT_ID, false);
355
0
        setFeature(XML_DECLARATION, false);
356
0
    }
357
    // Setting one of those parameters to true will set "canonical-form" to false.
358
0
    if ((featureId == FORMAT_PRETTY_PRINT_ID || featureId == DISCARD_DEFAULT_CONTENT_ID || featureId == XML_DECLARATION) && state)
359
0
        setFeature(CANONICAL_FORM_ID, false);
360
0
}
361
362
const void* DOMLSSerializerImpl::getParameter(const XMLCh* featName) const
363
0
{
364
0
    if(XMLString::compareIStringASCII(featName, XMLUni::fgDOMErrorHandler)==0)
365
0
    {
366
0
        return (void*)fErrorHandler;
367
0
    }
368
0
    else
369
0
    {
370
0
        int featureId = INVALID_FEATURE_ID;
371
0
        checkFeature(featName, true, featureId);
372
0
        return (void*)getFeature(featureId);
373
0
    }
374
0
}
375
376
const DOMStringList* DOMLSSerializerImpl::getParameterNames() const
377
0
{
378
0
    return fSupportedParameters;
379
0
}
380
381
void DOMLSSerializerImpl::setNewLine(const XMLCh* const newLine)
382
0
{
383
0
    fMemoryManager->deallocate(fNewLine);//delete [] fNewLine;
384
0
    fNewLine = XMLString::replicate(newLine, fMemoryManager);
385
0
}
386
387
const XMLCh* DOMLSSerializerImpl::getNewLine() const
388
0
{
389
0
    return fNewLine;
390
0
}
391
392
void DOMLSSerializerImpl::setFilter(DOMLSSerializerFilter *filter)
393
0
{
394
0
    fFilter = filter;
395
0
}
396
397
DOMLSSerializerFilter* DOMLSSerializerImpl::getFilter() const
398
0
{
399
0
    return fFilter;
400
0
}
401
402
//
403
//
404
//
405
bool DOMLSSerializerImpl::write(const DOMNode* nodeToWrite,
406
                                DOMLSOutput* const destination)
407
0
{
408
0
    XMLFormatTarget* pTarget=destination->getByteStream();
409
0
    Janitor<XMLFormatTarget> janTarget(0);
410
0
    if(!pTarget)
411
0
    {
412
0
        const XMLCh* szSystemId=destination->getSystemId();
413
0
        if(!szSystemId)
414
0
        {
415
            //TODO: report error "missing target"
416
0
            return false;
417
0
        }
418
0
        pTarget=new LocalFileFormatTarget(szSystemId, fMemoryManager);
419
0
        janTarget.reset(pTarget);
420
0
    }
421
    /**
422
     * When writing to a LSOutput, the encoding is found by looking at the encoding information
423
     * that is reachable through the LSOutput and the item to be written (or its owner document) in this order:
424
     *
425
     *  1. LSOutput.encoding,
426
     *  2. Document.inputEncoding,
427
     *  3. Document.xmlEncoding.
428
     *
429
     * If no encoding is reachable through the above properties, a default encoding of "UTF-8" will be used.
430
     * If the specified encoding is not supported an "unsupported-encoding" fatal error is raised.
431
     */
432
0
    fEncodingUsed = gUTF8;
433
434
0
    const DOMDocument *docu = (nodeToWrite->getNodeType() == DOMNode::DOCUMENT_NODE)?
435
0
                              (const DOMDocument*)nodeToWrite : nodeToWrite->getOwnerDocument();
436
437
0
    const XMLCh* lsEncoding=destination->getEncoding();
438
0
    if (lsEncoding && *lsEncoding)
439
0
    {
440
0
        fEncodingUsed = lsEncoding;
441
0
    }
442
0
    else if (docu)
443
0
    {
444
0
        const XMLCh* tmpEncoding = docu->getInputEncoding();
445
446
0
        if ( tmpEncoding && *tmpEncoding)
447
0
        {
448
0
            fEncodingUsed = tmpEncoding;
449
0
        }
450
0
        else
451
0
        {
452
0
            tmpEncoding = docu->getXmlEncoding();
453
454
0
            if ( tmpEncoding && *tmpEncoding)
455
0
            {
456
0
                fEncodingUsed = tmpEncoding;
457
0
            }
458
0
        }
459
0
    }
460
461
462
    /**
463
     *  The end-of-line sequence of characters to be used in the XML being
464
     *  written out. The only permitted values are these:
465
     *     . null
466
     *
467
     *  Use a default end-of-line sequence. DOM implementations should choose
468
     * the default to match the usual convention for text files in the
469
     * environment being used. Implementations must choose a default
470
     * sequence that matches one of those allowed by  2.11 "End-of-Line
471
     * Handling".
472
     *
473
     *    CR    The carriage-return character (#xD)
474
     *    CR-LF The carriage-return and line-feed characters (#xD #xA)
475
     *    LF    The line-feed character (#xA)
476
     *
477
     *  The default value for this attribute is null
478
     */
479
0
    fNewLineUsed = (fNewLine && *fNewLine)? fNewLine : gEOLSeq;
480
481
    /**
482
     *  get Document Version
483
     */
484
0
    fDocumentVersion = (docu && docu->getXmlVersion() && *(docu->getXmlVersion()))?docu->getXmlVersion():XMLUni::fgVersion1_0;
485
0
    fIsXml11 = XMLString::equals(fDocumentVersion, XMLUni::fgVersion1_1);
486
487
0
    fErrorCount = 0;
488
489
0
    fLineFeedInTextNodePrinted = false;
490
0
    fLastWhiteSpaceInTextNode = 0;
491
492
0
    try
493
0
    {
494
0
        fFormatter = new (fMemoryManager) XMLFormatter( fEncodingUsed
495
0
                                                       ,fDocumentVersion
496
0
                                                       ,pTarget
497
0
                                                       ,XMLFormatter::NoEscapes
498
0
                                                       ,XMLFormatter::UnRep_CharRef
499
0
                                                       ,fMemoryManager);
500
0
    }
501
0
    catch (const TranscodingException& e)
502
0
    {
503
0
        reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, e.getMessage());
504
0
        return false;
505
0
    }
506
507
0
    try
508
0
    {
509
0
        Janitor<XMLFormatter> janName(fFormatter);
510
0
        processNode(nodeToWrite);
511
0
        pTarget->flush();
512
0
    }
513
514
    //
515
    // The serialize engine (processNode) throws an exception to abort
516
    // serialization if
517
    //
518
    //   . A fatal error occurs which renders the output ill-formed, or
519
    //   . Instructed by the application's error handler
520
    //
521
0
    catch (const TranscodingException&)
522
0
    {
523
0
        pTarget->flush();
524
0
        return false;
525
0
    }
526
527
0
    catch (const XMLDOMMsg::Codes)
528
0
    {
529
0
        pTarget->flush();
530
0
        return false;
531
0
    }
532
0
    catch(const OutOfMemoryException&)
533
0
    {
534
0
        throw;
535
0
    }
536
0
    catch (...)
537
0
    {
538
0
        pTarget->flush();
539
0
        throw;
540
0
    }
541
542
    //
543
    // true if node was successfully serialized and
544
    // false in case a failure occured and the
545
    // failure wasn't canceled by the error handler.
546
    //
547
0
    return ((fErrorCount == 0)? true : false);
548
0
}
549
550
bool DOMLSSerializerImpl::writeToURI(const DOMNode* nodeToWrite, const XMLCh* uri)
551
0
{
552
0
    DOMLSOutputImpl output(fMemoryManager);
553
0
    output.setSystemId(uri);
554
0
    return write(nodeToWrite, &output);
555
0
}
556
557
//
558
// We don't throw DOMSTRING_SIZE_ERR since we are no longer
559
// using DOMString.
560
//
561
XMLCh* DOMLSSerializerImpl::writeToString(const DOMNode* nodeToWrite, MemoryManager* manager /*= NULL*/)
562
0
{
563
0
    if(manager==NULL)
564
0
        manager = fMemoryManager;
565
0
    MemBufFormatTarget  destination(1023, manager);
566
0
    bool retVal;
567
568
0
    bool bBOMFlag=getFeature(BYTE_ORDER_MARK_ID);
569
0
    setFeature(BYTE_ORDER_MARK_ID, false);
570
0
    try
571
0
    {
572
0
        DOMLSOutputImpl output(manager);
573
0
        output.setByteStream(&destination);
574
0
        output.setEncoding(XMLUni::fgUTF16EncodingString);
575
0
        retVal = write(nodeToWrite, &output);
576
0
    }
577
0
    catch(const OutOfMemoryException&)
578
0
    {
579
0
        throw;
580
0
    }
581
0
    catch (...)
582
0
    {
583
        //
584
        // there is a possibility that memory allocation
585
        // exception thrown in XMLBuffer class
586
        //
587
0
        setFeature(BYTE_ORDER_MARK_ID, bBOMFlag);
588
0
        return 0;
589
0
    }
590
591
0
    setFeature(BYTE_ORDER_MARK_ID, bBOMFlag);
592
0
    return (retVal ? XMLString::replicate(reinterpret_cast<const XMLCh*>(destination.getRawBuffer()), manager) : 0);
593
0
}
594
595
//
596
// Characters not representable in output encoding,
597
//
598
// 1. CHARACTER DATA (outside of markup)                --- no error
599
//    ordinary character  -> numeric character reference
600
//    '<' and '&'         -> &lt; and &amp;
601
//
602
// 2. Within MARKUP, but outside of attributes
603
//    reported as an error                                 --- ERROR
604
//    markup:
605
//           start tag                                  done
606
//           end tag                                    done
607
//           empty element tag                          done
608
//           entity references                          done
609
//           character references    // REVISIT
610
//           comments                                   done
611
//           CDATA section delimiters                   done, done
612
//           document type declarartions                done
613
//           processing instructions (PI)               done
614
//
615
// 3. With in ATTRIBUTE
616
//    -> numeric character reference
617
//    no quotes                        -> in quotes
618
//    with quotes, no apostrophe       -> in apostrophe
619
//    with quotes and apostrophe       -> in quotes and &quot;
620
//
621
// 4. CDATA sections
622
//    "split_cdata_section"  true                      --- char ref
623
//                           false                     ---      ERROR
624
//
625
// ---------------------------------------------------------------------------
626
//  Stream out a DOM node, and, recursively, all of its children. This
627
//  function is the heart of writing a DOM tree out as XML source. Give it
628
//  a document node and it will do the whole thing.
629
// ---------------------------------------------------------------------------
630
631
void DOMLSSerializerImpl::processNode(const DOMNode* const nodeToWrite, int level)
632
0
{
633
634
    // Get the name and value out for convenience
635
0
    const XMLCh*    nodeName = nodeToWrite->getNodeName();
636
0
    const XMLCh*    nodeValue = nodeToWrite->getNodeValue();
637
0
    XMLSize_t       lent = XMLString::stringLen(nodeValue);
638
639
0
    switch (nodeToWrite->getNodeType())
640
0
    {
641
0
    case DOMNode::TEXT_NODE:
642
0
        {
643
0
            if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT)
644
0
                break;
645
646
0
            ensureValidString(nodeToWrite, nodeValue);
647
0
            if (getFeature(FORMAT_PRETTY_PRINT_ID))
648
0
            {
649
0
                fLineFeedInTextNodePrinted = false;
650
0
                fLastWhiteSpaceInTextNode = 0;
651
652
0
                if(XMLChar1_0::isAllSpaces(nodeValue, XMLString::stringLen(nodeValue)))
653
0
                {
654
                    // skips whitespace-only text nodes unless whitespace-in-element is set.
655
0
                    if (!getFeature(WHITESPACE_IN_ELEMENT_CONTENT_ID))
656
0
                    {
657
0
                        break;
658
0
                    }
659
0
                    else
660
0
                    {
661
                        //
662
                        // we need to trace if newline(s) have been printed out
663
                        // to avoid generate extra newline for pretty printing,
664
                        // as well as the number of whitespaces after the last
665
                        // newline character to do indentation properly.
666
                        //
667
0
                        int pos = XMLString::lastIndexOf(nodeValue, chLF);
668
0
                        if (-1 != pos)
669
0
                        {
670
0
                            fLineFeedInTextNodePrinted = true;
671
0
                            fLastWhiteSpaceInTextNode = (unsigned int)(lent - pos);
672
0
                        }
673
0
                        else
674
0
                        {
675
                            // for those platforms using chCR alone as
676
                            // a newline character
677
0
                            pos = XMLString::lastIndexOf(nodeValue, chCR);
678
0
                            if (-1 != pos)
679
0
                            {
680
0
                                fLineFeedInTextNodePrinted = true;
681
0
                                fLastWhiteSpaceInTextNode = (unsigned int)(lent - pos);
682
0
                            }
683
0
                        }
684
0
                    }
685
0
                }
686
0
            }
687
688
0
            setURCharRef();      // character data
689
0
            fFormatter->formatBuf(nodeValue, lent, XMLFormatter::CharEscapes);
690
0
            break;
691
0
        }
692
693
0
    case DOMNode::PROCESSING_INSTRUCTION_NODE:
694
0
        {
695
0
            if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT)
696
0
                break;
697
698
0
            ensureValidString(nodeToWrite, nodeName);
699
0
            ensureValidString(nodeToWrite, nodeValue);
700
701
0
            if(level == 1 && getFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID))
702
0
                printNewLine();
703
704
0
            printNewLine();
705
0
            printIndent(level);
706
707
0
            TRY_CATCH_THROW
708
0
            (
709
0
                *fFormatter << XMLFormatter::NoEscapes << gStartPI << nodeName;
710
0
                if (lent > 0)
711
0
                {
712
0
                    *fFormatter << chSpace << nodeValue;
713
0
                }
714
0
                *fFormatter << gEndPI;
715
0
            )
716
0
            break;
717
0
        }
718
719
0
    case DOMNode::DOCUMENT_NODE: // Not to be shown to Filter
720
0
        {
721
722
            // output BOM if needed
723
0
            processBOM();
724
725
0
            setURCharRef();
726
0
            const DOMDocument *docu = (const DOMDocument*)nodeToWrite;
727
728
            //[23] XMLDecl      ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
729
            //[24] VersionInfo  ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
730
            //[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName
731
            //[32] SDDecl       ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))
732
            //
733
734
0
            if (getFeature(XML_DECLARATION)) {
735
                // use the version and encoding resolved
736
0
                *fFormatter << gXMLDecl_VersionInfo << fDocumentVersion << gXMLDecl_separator;
737
0
                *fFormatter << gXMLDecl_EncodingDecl << fEncodingUsed << gXMLDecl_separator;
738
739
0
                const XMLCh* st = (docu->getXmlStandalone())? XMLUni::fgYesString : XMLUni::fgNoString;
740
0
                *fFormatter << gXMLDecl_SDDecl << st << gXMLDecl_separator;
741
742
0
                *fFormatter << gXMLDecl_endtag;
743
0
            }
744
745
0
            DOMNodeSPtr child = nodeToWrite->getFirstChild();
746
0
            while( child != 0)
747
0
            {
748
0
                processNode(child, level);
749
0
                child = child->getNextSibling();
750
0
            }
751
0
            printNewLine();
752
0
            break;
753
0
        }
754
755
0
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
756
0
        {
757
758
0
            setURCharRef();
759
760
0
            DOMNode *child = nodeToWrite->getFirstChild();
761
0
            while( child != 0)
762
0
            {
763
0
                processNode(child, level);
764
0
                child = child->getNextSibling();
765
0
            }
766
0
            printNewLine();
767
0
            break;
768
0
        }
769
770
0
    case DOMNode::ELEMENT_NODE:
771
0
        {
772
0
            DOMNodeFilter::FilterAction filterAction = checkFilter(nodeToWrite);
773
774
0
            if ( filterAction == DOMNodeFilter::FILTER_REJECT)
775
0
                break;
776
777
0
            if (!fLineFeedInTextNodePrinted)
778
0
            {
779
0
                if(level == 1 && getFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID))
780
0
                    printNewLine();
781
782
0
                printNewLine();
783
0
            }
784
0
            else
785
0
            {
786
0
                fLineFeedInTextNodePrinted = false;
787
0
            }
788
789
0
            printIndent(level);
790
791
            //track the line number the current node begins on
792
0
            int nodeLine = fCurrentLine;
793
794
            // add an entry in the namespace stack
795
0
            RefHashTableOf<XMLCh>* namespaceMap=NULL;
796
797
0
            if ( filterAction == DOMNodeFilter::FILTER_ACCEPT)
798
0
            {
799
                //           this element    attributes   child elements
800
                // accept        yes             yes           yes
801
                // skip          no              no            yes
802
                //
803
0
                TRY_CATCH_THROW
804
0
                (
805
                // The name has to be representable without any escapes
806
0
                    *fFormatter  << XMLFormatter::NoEscapes
807
0
                                 << chOpenAngle << nodeName;
808
0
                )
809
810
                // Output any attributes on this element
811
0
                setURCharRef();
812
0
                DOMNamedNodeMap *attributes = nodeToWrite->getAttributes();
813
0
                XMLSize_t attrCount = attributes->getLength();
814
815
                // check if the namespace for the current node is already defined
816
0
                const XMLCh* prefix = nodeToWrite->getPrefix();
817
0
                const XMLCh* uri = nodeToWrite->getNamespaceURI();
818
0
                if((uri && uri[0]) || ((prefix==0 || prefix[0]==0) && isDefaultNamespacePrefixDeclared()))
819
0
                {
820
0
                    if(prefix==0 || prefix[0]==0)
821
0
                        prefix=XMLUni::fgZeroLenString;
822
0
                    if(!isNamespaceBindingActive(prefix, uri))
823
0
                    {
824
0
                        if(namespaceMap==NULL)
825
0
                        {
826
0
                            namespaceMap=new (fMemoryManager) RefHashTableOf<XMLCh>(12, false, fMemoryManager);
827
0
                            fNamespaceStack->addElement(namespaceMap);
828
0
                        }
829
0
                        namespaceMap->put((void*)prefix,(XMLCh*)uri);
830
0
                        *fFormatter  << XMLFormatter::NoEscapes
831
0
                                     << chSpace << XMLUni::fgXMLNSString;
832
0
                        if(!XMLString::equals(prefix,XMLUni::fgZeroLenString))
833
0
                            *fFormatter  << chColon << prefix;
834
0
                        *fFormatter  << chEqual << chDoubleQuote
835
0
                                     << XMLFormatter::AttrEscapes
836
0
                                     << uri
837
0
                                     << XMLFormatter::NoEscapes
838
0
                                     << chDoubleQuote;
839
0
                    }
840
0
                }
841
842
0
                bool discard = getFeature(DISCARD_DEFAULT_CONTENT_ID);
843
0
                for (XMLSize_t i = 0; i < attrCount; i++)
844
0
                {
845
0
                    DOMAttrSPtr  attribute = (DOMAttr*)attributes->item(i);
846
847
                    // Not to be shown to Filter
848
849
                    //
850
                    //"discard-default-content"
851
                    //    true
852
                    //    [required] (default)
853
                    //    Use whatever information available to the implementation
854
                    //  (i.e. XML schema, DTD, the specified flag on Attr nodes,
855
                    //  and so on) to decide what attributes and content should be
856
                    //  discarded or not.
857
                    //  Note that the specified flag on Attr nodes in itself is
858
                    //  not always reliable, it is only reliable when it is set
859
                    //  to false since the only case where it can be set to false
860
                    //  is if the attribute was created by the implementation.
861
                    //  The default content won't be removed if an implementation
862
                    //  does not have any information available.
863
                    //    false
864
                    //    [required]
865
                    //    Keep all attributes and all content.
866
                    //
867
0
                    if (discard && !((DOMAttr*)attribute )->getSpecified())
868
0
                        continue;
869
                    //
870
                    //  Again the name has to be completely representable. But the
871
                    //  attribute can have refs and requires the attribute style
872
                    //  escaping.
873
                    //
874
875
                    // if this attribute is a namespace declaration, add it to the namespace map for the current level
876
0
                    const XMLCh* ns = attribute->getNamespaceURI();
877
0
                    if (ns != 0 )
878
0
                    {
879
0
                        if(XMLString::equals(ns, XMLUni::fgXMLNSURIName))
880
0
                        {
881
0
                            if(namespaceMap==NULL)
882
0
                            {
883
0
                                namespaceMap=new (fMemoryManager) RefHashTableOf<XMLCh>(12, false, fMemoryManager);
884
0
                                fNamespaceStack->addElement(namespaceMap);
885
0
                            }
886
0
                            const XMLCh* nsPrefix = attribute->getLocalName();
887
0
                            if(XMLString::equals(attribute->getNodeName(),XMLUni::fgXMLNSString))
888
0
                                nsPrefix = XMLUni::fgZeroLenString;
889
0
                            if(namespaceMap->containsKey((void*)nsPrefix))
890
0
                                continue;
891
0
                            namespaceMap->put((void*)attribute->getLocalName(),(XMLCh*)attribute->getNodeValue());
892
0
                        }
893
0
                        else if(!XMLString::equals(ns, XMLUni::fgXMLURIName))
894
0
                        {
895
                            // check if the namespace for the current node is already defined
896
0
                            const XMLCh* prefix = attribute->getPrefix();
897
0
                            if(prefix && prefix[0])
898
0
                            {
899
0
                                const XMLCh* uri = attribute->getNamespaceURI();
900
0
                                if(!isNamespaceBindingActive(prefix, uri))
901
0
                                {
902
0
                                    if(namespaceMap==NULL)
903
0
                                    {
904
0
                                        namespaceMap=new (fMemoryManager) RefHashTableOf<XMLCh>(12, false, fMemoryManager);
905
0
                                        fNamespaceStack->addElement(namespaceMap);
906
0
                                    }
907
0
                                    namespaceMap->put((void*)prefix,(XMLCh*)uri);
908
0
                                    *fFormatter  << XMLFormatter::NoEscapes
909
0
                                                 << chSpace << XMLUni::fgXMLNSString << chColon << prefix
910
0
                                                 << chEqual << chDoubleQuote
911
0
                                                 << XMLFormatter::AttrEscapes
912
0
                                                 << uri
913
0
                                                 << XMLFormatter::NoEscapes
914
0
                                                 << chDoubleQuote;
915
0
                                }
916
0
                            }
917
0
                        }
918
0
                    }
919
0
                    if (XMLString::equals(ns, XMLUni::fgXMLNSURIName) || checkFilter(attribute) == DOMNodeFilter::FILTER_ACCEPT)
920
0
                    {
921
0
                        *fFormatter  << XMLFormatter::NoEscapes
922
0
                                     << chSpace << attribute->getNodeName()
923
0
                                     << chEqual << chDoubleQuote
924
0
                                     << XMLFormatter::AttrEscapes;
925
0
                        if (getFeature(ENTITIES_ID))
926
0
                        {
927
0
                            DOMNodeSPtr child = attribute->getFirstChild();
928
0
                            while( child != 0)
929
0
                            {
930
0
                                if(child->getNodeType()==DOMNode::TEXT_NODE)
931
0
                                {
932
0
                                    ensureValidString(attribute, child->getNodeValue());
933
0
                                    *fFormatter  << child->getNodeValue();
934
0
                                }
935
0
                                else if(child->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
936
0
                                    *fFormatter << XMLFormatter::NoEscapes
937
0
                                                << chAmpersand << child->getNodeName() << chSemiColon
938
0
                                                << XMLFormatter::AttrEscapes;
939
0
                                child = child->getNextSibling();
940
0
                            }
941
0
                        }
942
0
                        else
943
0
                        {
944
0
                            ensureValidString(attribute, attribute->getNodeValue());
945
0
                            *fFormatter  << attribute->getNodeValue();
946
0
                        }
947
0
                        *fFormatter  << XMLFormatter::NoEscapes
948
0
                                     << chDoubleQuote;
949
0
                    }
950
0
                } // end of for
951
0
            } // end of FILTER_ACCEPT
952
953
0
            level++;
954
955
            // FILTER_SKIP may start from here
956
957
            //
958
            //  Test for the presence of children, which includes both
959
            //  text content and nested elements.
960
            //
961
0
            DOMNodeSPtr child = nodeToWrite->getFirstChild();
962
0
            if (child != 0)
963
0
            {
964
                // There are children. Close start-tag, and output children.
965
                // No escapes are legal here
966
0
                if (filterAction == DOMNodeFilter::FILTER_ACCEPT)
967
0
                    *fFormatter << XMLFormatter::NoEscapes << chCloseAngle;
968
969
0
                while( child != 0)
970
0
                {
971
0
                    processNode(child, level);
972
0
                    child = child->getNextSibling();
973
0
                }
974
975
0
                level--;
976
977
0
                if (filterAction == DOMNodeFilter::FILTER_ACCEPT)
978
0
                {
979
                    //if we are not on the same line as when we started
980
                    //this node then print a new line and indent
981
0
                    if(nodeLine != fCurrentLine)
982
0
                    {
983
0
                        if (!fLineFeedInTextNodePrinted)
984
0
                        {
985
0
                            printNewLine();
986
0
                        }
987
0
                        else
988
0
                        {
989
0
                            fLineFeedInTextNodePrinted = false;
990
0
                        }
991
992
0
                        if(nodeLine != fCurrentLine && level == 0 && getFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID))
993
0
                            printNewLine();
994
995
0
                        printIndent(level);
996
0
                    }
997
0
                    TRY_CATCH_THROW
998
0
                    (
999
0
                         *fFormatter << XMLFormatter::NoEscapes << gEndElement
1000
0
                                     << nodeName << chCloseAngle;
1001
0
                    )
1002
1003
0
                }
1004
0
            }
1005
0
            else
1006
0
            {
1007
0
                level--;
1008
1009
                //
1010
                //  There were no children. Output the short form close of
1011
                //  the element start tag, making it an empty-element tag.
1012
                //
1013
0
                if (filterAction == DOMNodeFilter::FILTER_ACCEPT)
1014
0
                {
1015
0
                    TRY_CATCH_THROW
1016
0
                    (
1017
0
                        *fFormatter << XMLFormatter::NoEscapes << chForwardSlash << chCloseAngle;
1018
0
                    )
1019
0
                }
1020
0
            }
1021
1022
            // remove the namespace map at this level
1023
0
            if(namespaceMap!=NULL)
1024
0
                fNamespaceStack->removeLastElement();
1025
1026
0
            break;
1027
0
        }
1028
0
    case DOMNode::ATTRIBUTE_NODE:
1029
0
        {
1030
0
            if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT)
1031
0
                break;
1032
1033
0
            const XMLCh* localName = nodeToWrite->getLocalName();
1034
1035
            // check if this is a DOM Level 1 Node
1036
0
            if(localName == 0)
1037
0
                *fFormatter  << XMLFormatter::NoEscapes
1038
0
                             << nodeToWrite->getNodeName();
1039
0
            else
1040
0
                *fFormatter  << XMLFormatter::NoEscapes
1041
0
                             << chOpenCurly << nodeToWrite->getNamespaceURI()
1042
0
                             << chCloseCurly << localName;
1043
0
            *fFormatter  << chEqual << chDoubleQuote
1044
0
                         << XMLFormatter::AttrEscapes;
1045
0
            if (getFeature(ENTITIES_ID))
1046
0
            {
1047
0
                DOMNodeSPtr child = nodeToWrite->getFirstChild();
1048
0
                while( child != 0)
1049
0
                {
1050
0
                    if(child->getNodeType()==DOMNode::TEXT_NODE)
1051
0
                    {
1052
0
                        ensureValidString(nodeToWrite, child->getNodeValue());
1053
0
                        *fFormatter  << child->getNodeValue();
1054
0
                    }
1055
0
                    else if(child->getNodeType()==DOMNode::ENTITY_REFERENCE_NODE)
1056
0
                        *fFormatter << XMLFormatter::NoEscapes
1057
0
                                    << chAmpersand << child->getNodeName() << chSemiColon
1058
0
                                    << XMLFormatter::AttrEscapes;
1059
0
                    child = child->getNextSibling();
1060
0
                }
1061
0
            }
1062
0
            else
1063
0
            {
1064
0
                ensureValidString(nodeToWrite, nodeValue);
1065
0
                *fFormatter  << nodeValue;
1066
0
            }
1067
0
            *fFormatter  << XMLFormatter::NoEscapes
1068
0
                         << chDoubleQuote;
1069
1070
0
            break;
1071
0
        }
1072
0
    case DOMNode::ENTITY_REFERENCE_NODE:
1073
0
        {
1074
            //"entities"
1075
            //true
1076
            //[required] (default)
1077
            //Keep EntityReference and Entity nodes in the document.
1078
1079
            //false
1080
            //[optional]
1081
            //Remove all EntityReference and Entity nodes from the document,
1082
            //       putting the entity expansions directly in their place.
1083
            //       Text nodes are into "normal" form.
1084
            //Only EntityReference nodes to non-defined entities are kept in the document.
1085
1086
0
            if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT)
1087
0
                break;
1088
1089
0
            if (getFeature(ENTITIES_ID))
1090
0
            {
1091
0
                TRY_CATCH_THROW
1092
0
                (
1093
0
                    *fFormatter << XMLFormatter::NoEscapes << chAmpersand
1094
0
                                << nodeName << chSemiColon;
1095
0
                )
1096
0
            }
1097
0
            else
1098
0
            {
1099
                // check if the referenced entity is defined or not
1100
0
                if (nodeToWrite->getOwnerDocument()->getDoctype()->getEntities()->getNamedItem(nodeName))
1101
0
                {
1102
0
                    DOMNodeSPtr child;
1103
0
                    for (child = nodeToWrite->getFirstChild();
1104
0
                    child != 0;
1105
0
                    child = child->getNextSibling())
1106
0
                    {
1107
0
                        processNode(child, level);
1108
0
                    }
1109
0
                }
1110
0
                else
1111
0
                {
1112
0
                    TRY_CATCH_THROW
1113
0
                   (
1114
0
                        *fFormatter<<XMLFormatter::NoEscapes<<chAmpersand<<nodeName<<chSemiColon;
1115
0
                    )
1116
0
                }
1117
0
            }
1118
0
            break;
1119
0
        }
1120
1121
        //
1122
        //  feature:split_cdata_sections     occurence of ]]>   unrep-char
1123
        //  ===============================================================
1124
        //          true                        split            split
1125
        //          false                       fails            fails
1126
        //
1127
0
    case DOMNode::CDATA_SECTION_NODE:
1128
0
        {
1129
0
            if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT)
1130
0
                break;
1131
1132
0
            if (getFeature(SPLIT_CDATA_SECTIONS_ID))
1133
0
            {
1134
                // it is fairly complicated and we process this
1135
                // in a separate function.
1136
0
                procCdataSection(nodeValue, nodeToWrite);
1137
0
            }
1138
0
            else
1139
0
            {
1140
0
                ensureValidString(nodeToWrite, nodeValue);
1141
                // search for "]]>", the node value is not supposed to have this
1142
0
                if (XMLString::patternMatch(nodeValue, gEndCDATA) != -1)
1143
0
                {
1144
0
                    reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, XMLDOMMsg::Writer_NestedCDATA);
1145
0
                }
1146
1147
0
                TRY_CATCH_THROW
1148
0
                (
1149
                    // transcoder throws exception for unrep chars
1150
0
                    *fFormatter << XMLFormatter::NoEscapes << gStartCDATA << nodeValue << gEndCDATA;
1151
0
                )
1152
0
            }
1153
1154
0
            break;
1155
0
        }
1156
1157
0
    case DOMNode::COMMENT_NODE:
1158
0
        {
1159
0
            if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT)
1160
0
                break;
1161
1162
0
            ensureValidString(nodeToWrite, nodeValue);
1163
1164
            // Figure out if we want pretty-printing for this comment.
1165
            // If this comment node does not have any element siblings
1166
            // (i.e., it is a text node) then we don't want to add any
1167
            // whitespaces since that might be significant to the
1168
            // application. Otherwise we want pretty-printing.
1169
            //
1170
1171
0
            bool pretty = (level == 0); // Document-level comments.
1172
1173
0
            if (!pretty)
1174
0
            {
1175
                // See if we have any element siblings.
1176
                //
1177
0
                const DOMNode* s = nodeToWrite->getNextSibling ();
1178
1179
0
                while (s != 0 && s->getNodeType () != DOMNode::ELEMENT_NODE)
1180
0
                    s = s->getNextSibling ();
1181
1182
0
                if (s != 0)
1183
0
                    pretty = true;
1184
0
                else
1185
0
                {
1186
0
                    s = nodeToWrite->getPreviousSibling ();
1187
1188
0
                    while (s != 0 && s->getNodeType () != DOMNode::ELEMENT_NODE)
1189
0
                        s = s->getPreviousSibling ();
1190
1191
0
                    if (s != 0)
1192
0
                       pretty = true;
1193
0
                }
1194
0
            }
1195
1196
0
            if (pretty)
1197
0
            {
1198
0
                if(level == 1 && getFeature(FORMAT_PRETTY_PRINT_1ST_LEVEL_ID))
1199
0
                    printNewLine();
1200
1201
0
                printNewLine();
1202
0
                printIndent(level);
1203
0
            }
1204
1205
0
            TRY_CATCH_THROW
1206
0
            (
1207
0
                *fFormatter << XMLFormatter::NoEscapes << gStartComment
1208
0
                            << nodeValue << gEndComment;
1209
0
            )
1210
0
            break;
1211
0
        }
1212
1213
0
    case DOMNode::DOCUMENT_TYPE_NODE:  // Not to be shown to Filter
1214
0
        {
1215
0
            const DOMDocumentType *doctype = (const DOMDocumentType *)nodeToWrite;
1216
1217
0
            fFormatter->setEscapeFlags(XMLFormatter::NoEscapes);
1218
1219
0
            printNewLine();
1220
0
            printIndent(level);
1221
1222
0
            TRY_CATCH_THROW
1223
0
            (
1224
0
                *fFormatter << gStartDoctype << nodeName;
1225
1226
0
                const XMLCh  *id = doctype->getPublicId();
1227
0
                if (id && *id)
1228
0
                {
1229
0
                    *fFormatter << chSpace << gPublic << id << chDoubleQuote;
1230
1231
0
                    id = doctype->getSystemId();
1232
0
                    if (id && *id)
1233
0
                    {
1234
0
                        *fFormatter << chSpace << chDoubleQuote << id << chDoubleQuote;
1235
0
                    }
1236
0
                    else
1237
0
                    {
1238
                        //
1239
                        // 4.2.2 External Entities
1240
                        // [Definition: If the entity is not internal,
1241
                        //           it is an external entity, declared as follows:]
1242
                        // External Entity Declaration
1243
                        // [75] ExternalID ::= 'SYSTEM' S SystemLiteral
1244
                        //                   | 'PUBLIC' S PubidLiteral S SystemLiteral
1245
                        //
1246
0
                        reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, XMLDOMMsg::Writer_NotRecognizedType);
1247
                        // systemLiteral not found
1248
0
                    }
1249
0
                }
1250
0
                else
1251
0
                {
1252
0
                    id = doctype->getSystemId();
1253
0
                    if (id && *id)
1254
0
                    {
1255
0
                        *fFormatter << chSpace << gSystem << id << chDoubleQuote;
1256
0
                    }
1257
0
                }
1258
1259
0
                id = doctype->getInternalSubset();
1260
0
                if (id && *id)
1261
0
                {
1262
0
                    *fFormatter << chSpace << chOpenSquare << id << chCloseSquare;
1263
0
                }
1264
1265
0
                *fFormatter << chCloseAngle;
1266
            ) // end of TRY_CATCH_THROW
1267
0
1268
0
            break;
1269
0
        }
1270
1271
0
    case DOMNode::ENTITY_NODE:  // Not to be shown to Filter
1272
0
        {
1273
            //
1274
            // REVISIT: how does the feature "entities" impact
1275
            // entity node?
1276
            //
1277
0
            printNewLine();
1278
0
            printIndent(level);
1279
1280
0
            fFormatter->setEscapeFlags(XMLFormatter::NoEscapes);
1281
0
            *fFormatter << gStartEntity    << nodeName;
1282
1283
0
            const XMLCh * id = ((const DOMEntity*)nodeToWrite)->getPublicId();
1284
0
            if (id)
1285
0
                *fFormatter << gPublic << id << chDoubleQuote;
1286
1287
0
            id = ((const DOMEntity*)nodeToWrite)->getSystemId();
1288
0
            if (id)
1289
0
                *fFormatter << gSystem << id << chDoubleQuote;
1290
1291
0
            id = ((const DOMEntity*)nodeToWrite)->getNotationName();
1292
0
            if (id)
1293
0
                *fFormatter << gNotation << id << chDoubleQuote;
1294
1295
0
            *fFormatter << chCloseAngle;
1296
1297
0
            break;
1298
0
        }
1299
1300
0
    default:
1301
        /***
1302
            This is an implementation specific behaviour, we abort if a user derived class has not dealt with
1303
            this node type.
1304
         ***/
1305
0
        {
1306
0
            if(!customNodeSerialize(nodeToWrite, level)) {
1307
0
                reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, XMLDOMMsg::Writer_NotRecognizedType);
1308
                // UnreognizedNodeType;
1309
0
            }
1310
0
        }
1311
1312
0
        break;
1313
0
    }
1314
1315
0
}
1316
1317
0
bool DOMLSSerializerImpl::customNodeSerialize(const DOMNode* const, int) {
1318
0
    return false;
1319
0
}
1320
1321
//
1322
//
1323
DOMNodeFilter::FilterAction DOMLSSerializerImpl::checkFilter(const DOMNode* const node) const
1324
0
{
1325
0
    if (!fFilter ||
1326
0
        ((fFilter->getWhatToShow() & (1 << (node->getNodeType() - 1))) == 0))
1327
0
        return DOMNodeFilter::FILTER_ACCEPT;
1328
1329
    //
1330
    // if and only if there is a filter, and it is interested
1331
    // in the node type, then we pass the node to the filter
1332
    // for examination
1333
    //
1334
0
    return (DOMNodeFilter::FilterAction) fFilter->acceptNode(node);
1335
0
}
1336
1337
1338
bool DOMLSSerializerImpl::checkFeature(const XMLCh* const featName
1339
                               , bool               toThrow
1340
                               , int&               featureId) const
1341
0
{
1342
    // check for null and/or empty feature name
1343
0
    if (!featName || !*featName)
1344
0
    {
1345
0
        if (toThrow)
1346
0
            throw DOMException(DOMException::NOT_FOUND_ERR, 0, fMemoryManager);
1347
1348
0
        return false;
1349
0
    }
1350
1351
0
    featureId = INVALID_FEATURE_ID;
1352
1353
0
    if (XMLString::equals(featName, XMLUni::fgDOMWRTCanonicalForm))
1354
0
        featureId = CANONICAL_FORM_ID;
1355
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTDiscardDefaultContent))
1356
0
        featureId = DISCARD_DEFAULT_CONTENT_ID;
1357
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTEntities))
1358
0
        featureId = ENTITIES_ID;
1359
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTFormatPrettyPrint))
1360
0
        featureId = FORMAT_PRETTY_PRINT_ID;
1361
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTNormalizeCharacters))
1362
0
        featureId = NORMALIZE_CHARACTERS_ID;
1363
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTSplitCdataSections))
1364
0
        featureId = SPLIT_CDATA_SECTIONS_ID;
1365
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTValidation))
1366
0
        featureId = VALIDATION_ID;
1367
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTWhitespaceInElementContent))
1368
0
        featureId = WHITESPACE_IN_ELEMENT_CONTENT_ID;
1369
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTBOM))
1370
0
        featureId = BYTE_ORDER_MARK_ID;
1371
0
    else if (XMLString::equals(featName, XMLUni::fgDOMXMLDeclaration))
1372
0
        featureId = XML_DECLARATION;
1373
0
    else if (XMLString::equals(featName, XMLUni::fgDOMWRTXercesPrettyPrint))
1374
0
        featureId = FORMAT_PRETTY_PRINT_1ST_LEVEL_ID;
1375
1376
1377
    //feature name not resolvable
1378
0
    if (featureId == INVALID_FEATURE_ID)
1379
0
    {
1380
0
        if (toThrow)
1381
0
            throw DOMException(DOMException::NOT_FOUND_ERR, 0, fMemoryManager);
1382
1383
0
        return false;
1384
0
    }
1385
1386
0
    return true;
1387
0
}
1388
1389
bool DOMLSSerializerImpl::reportError(const DOMNode* const    errorNode
1390
                              , DOMError::ErrorSeverity errorType
1391
                              , const XMLCh*   const    errorMsg)
1392
0
{
1393
0
    bool toContinueProcess = true;   // default value for no error handler
1394
1395
0
    if (fErrorHandler)
1396
0
    {
1397
0
        DOMLocatorImpl  locator(0, 0, (DOMNode*) errorNode, 0);
1398
0
        DOMErrorImpl    domError(errorType , errorMsg, &locator);
1399
0
        try
1400
0
        {
1401
0
            toContinueProcess = fErrorHandler->handleError(domError);
1402
0
        }
1403
0
        catch(...)
1404
0
        {
1405
0
        }
1406
0
    }
1407
1408
0
    if (errorType != DOMError::DOM_SEVERITY_WARNING)
1409
0
        fErrorCount++;
1410
1411
0
    return toContinueProcess;
1412
0
}
1413
1414
bool DOMLSSerializerImpl::reportError(const DOMNode* const    errorNode
1415
                              , DOMError::ErrorSeverity errorType
1416
                              , XMLDOMMsg::Codes        toEmit)
1417
0
{
1418
0
    const XMLSize_t msgSize = 1023;
1419
0
    XMLCh errText[msgSize + 1];
1420
1421
0
    DOMImplementationImpl::getMsgLoader4DOM()->loadMsg(toEmit, errText, msgSize);
1422
1423
0
    bool toContinueProcess = true;   // default value for no error handler
1424
1425
0
    if (fErrorHandler)
1426
0
    {
1427
0
        DOMLocatorImpl  locator(0, 0, (DOMNode*) errorNode, 0);
1428
0
        DOMErrorImpl    domError(errorType , errText, &locator);
1429
0
        try
1430
0
        {
1431
0
            toContinueProcess = fErrorHandler->handleError(domError);
1432
0
        }
1433
0
        catch(...)
1434
0
        {
1435
0
        }
1436
0
    }
1437
1438
0
    if (errorType != DOMError::DOM_SEVERITY_WARNING)
1439
0
        fErrorCount++;
1440
1441
0
    if (errorType == DOMError::DOM_SEVERITY_FATAL_ERROR || !toContinueProcess)
1442
0
        throw DOMLSException(DOMLSException::SERIALIZE_ERR, toEmit, fMemoryManager);
1443
1444
0
    return toContinueProcess;
1445
0
}
1446
1447
//
1448
//
1449
//
1450
void DOMLSSerializerImpl::procCdataSection(const XMLCh*   const nodeValue
1451
                                   , const DOMNode* const nodeToWrite)
1452
0
{
1453
0
    static const XMLSize_t offset = XMLString::stringLen(gEndCDATA);
1454
1455
    /***
1456
     * Append a ']]>' at the end
1457
     */
1458
0
    XMLSize_t len = XMLString::stringLen(nodeValue);
1459
0
    XMLCh* repNodeValue = (XMLCh*) fMemoryManager->allocate
1460
0
    (
1461
0
        (len + offset + 1) * sizeof(XMLCh)
1462
0
    );//new XMLCh [len + offset + 1];
1463
0
    XMLString::copyString(repNodeValue, nodeValue);
1464
0
    XMLString::catString(repNodeValue, gEndCDATA);
1465
0
    ArrayJanitor<XMLCh>  jName(repNodeValue, fMemoryManager);
1466
1467
0
    XMLCh* curPtr  = (XMLCh*) repNodeValue;
1468
0
    XMLCh* nextPtr = 0;
1469
0
    int    endTagPos = -1;
1470
1471
0
    bool   endTagFound = true;
1472
1473
0
    while (endTagFound)
1474
0
    {
1475
0
        endTagPos = XMLString::patternMatch(curPtr, gEndCDATA);
1476
0
        if (endTagPos != -1)
1477
0
        {
1478
0
            nextPtr = curPtr + endTagPos + offset;  // skip the ']]>'
1479
0
            *(curPtr + endTagPos) = chNull;         //nullify the first ']'
1480
0
            if (XMLSize_t(endTagPos) != len)
1481
0
                reportError(nodeToWrite, DOMError::DOM_SEVERITY_WARNING, XMLDOMMsg::Writer_NestedCDATA);
1482
0
            len = len - endTagPos - offset;
1483
0
        }
1484
0
        else
1485
0
        {
1486
0
            endTagFound = false;
1487
0
        }
1488
1489
        /***
1490
            to check ]]>]]>
1491
        ***/
1492
0
        if (endTagPos == 0)
1493
0
        {
1494
0
            TRY_CATCH_THROW
1495
0
            (
1496
0
                *fFormatter << XMLFormatter::NoEscapes << gStartCDATA << gEndCDATA;
1497
0
            )
1498
0
        }
1499
0
        else
1500
0
        {
1501
0
            procUnrepCharInCdataSection(curPtr, nodeToWrite);
1502
0
        }
1503
1504
0
        if (endTagFound)
1505
0
        {
1506
0
            *(nextPtr - offset) = chCloseSquare;   //restore the first ']'
1507
0
            curPtr = nextPtr;
1508
0
        }
1509
0
    }
1510
0
}
1511
1512
//
1513
//
1514
//
1515
void DOMLSSerializerImpl::procUnrepCharInCdataSection(const XMLCh*   const nodeValue
1516
                                              , const DOMNode* const nodeToWrite)
1517
0
{
1518
    //
1519
    //  We have to check each character and see if it could be represented.
1520
    //  As long as it can, we just keep up with where we started and how
1521
    //  many chars we've checked. When we hit an unrepresentable one, we
1522
    //  stop, transcode everything we've collected, then start handling
1523
    //  the unrepresentables via char refs. We repeat this until we get all
1524
    //  the chars done.
1525
    //
1526
0
    const XMLCh*    srcPtr = nodeValue;
1527
0
    const XMLCh*    endPtr = nodeValue +  XMLString::stringLen(nodeValue);
1528
1529
    // Set up the common part of the buffer that we build char refs into
1530
0
    XMLCh tmpBuf[32];
1531
0
    tmpBuf[0] = chAmpersand;
1532
0
    tmpBuf[1] = chPound;
1533
0
    tmpBuf[2] = chLatin_x;
1534
1535
0
    while (srcPtr < endPtr)
1536
0
    {
1537
0
        const XMLCh* tmpPtr = srcPtr;
1538
0
        while (tmpPtr < endPtr)
1539
0
        {
1540
0
            if (fFormatter->getTranscoder()->canTranscodeTo(*tmpPtr))
1541
0
                tmpPtr++;
1542
0
            else
1543
0
                break;
1544
0
        }
1545
1546
0
        if (tmpPtr > srcPtr)
1547
0
        {
1548
0
            TRY_CATCH_THROW
1549
0
            (
1550
0
                *fFormatter << XMLFormatter::NoEscapes << gStartCDATA;
1551
0
            )
1552
1553
            // We got at least some chars that can be done normally
1554
0
            fFormatter->formatBuf
1555
0
            (
1556
0
                srcPtr
1557
0
                , tmpPtr - srcPtr
1558
0
                , XMLFormatter::NoEscapes
1559
0
                , XMLFormatter::UnRep_Fail
1560
0
            );
1561
1562
0
            TRY_CATCH_THROW
1563
0
            (
1564
0
                *fFormatter << XMLFormatter::NoEscapes << gEndCDATA;
1565
0
            )
1566
1567
            // Update the source pointer to our new spot
1568
0
            srcPtr = tmpPtr;
1569
0
        }
1570
0
        else
1571
0
        {
1572
            //
1573
            //  We hit something unrepresentable. So continue forward doing
1574
            //  char refs until we hit something representable again or the
1575
            //  end of input.
1576
            //
1577
1578
            // one warning for consective unrep chars
1579
0
            reportError(nodeToWrite, DOMError::DOM_SEVERITY_WARNING, XMLDOMMsg::Writer_NotRepresentChar);
1580
1581
0
            while (srcPtr < endPtr)
1582
0
            {
1583
                // Build a char ref for the current char
1584
0
                XMLString::binToText(*srcPtr, &tmpBuf[3], 8, 16, fMemoryManager);
1585
0
                const XMLSize_t bufLen = XMLString::stringLen(tmpBuf);
1586
0
                tmpBuf[bufLen] = chSemiColon;
1587
0
                tmpBuf[bufLen+1] = chNull;
1588
1589
                // And now call recursively back to our caller to format this
1590
0
                fFormatter->formatBuf
1591
0
                (
1592
0
                    tmpBuf
1593
0
                    , bufLen + 1
1594
0
                    , XMLFormatter::NoEscapes
1595
0
                    , XMLFormatter::UnRep_Fail
1596
0
                );
1597
1598
                // Move up the source pointer and break out if needed
1599
0
                srcPtr++;
1600
0
                if (fFormatter->getTranscoder()->canTranscodeTo(*srcPtr))
1601
0
                    break;
1602
0
            }
1603
0
        }
1604
0
    }
1605
0
}
1606
1607
void DOMLSSerializerImpl::processNode(const DOMNode* const nodeToWrite)
1608
0
{
1609
0
    processNode(nodeToWrite, 0);
1610
0
}
1611
1612
bool DOMLSSerializerImpl::canSetFeature(const int featureId
1613
                                       , bool      val) const
1614
0
{
1615
0
    return featuresSupported[2*featureId + (val? 0: 1)];
1616
0
}
1617
1618
void DOMLSSerializerImpl::printNewLine()
1619
0
{
1620
0
    if (getFeature(FORMAT_PRETTY_PRINT_ID))
1621
0
    {
1622
0
        fCurrentLine++;
1623
0
        *fFormatter << fNewLineUsed;
1624
0
    }
1625
0
}
1626
1627
void DOMLSSerializerImpl::printIndent(unsigned int level)
1628
0
{
1629
0
    if (getFeature(FORMAT_PRETTY_PRINT_ID))
1630
0
    {
1631
0
        if (fLastWhiteSpaceInTextNode)
1632
0
        {
1633
0
            unsigned int indentLevel = fLastWhiteSpaceInTextNode/2; // two chSpaces equals one indent level
1634
0
            fLastWhiteSpaceInTextNode = 0;
1635
            // if fLastWhiteSpaceInTextNode/2 is greater than level, then
1636
            // it means too many spaces have been written to the
1637
            // output stream and we can no longer indent properly
1638
0
            if(indentLevel < level)
1639
0
                level -= indentLevel;
1640
0
            else
1641
0
                level = 0;
1642
0
        }
1643
1644
0
        for(unsigned int i = 0; i < level; i++)
1645
0
            *fFormatter << chSpace << chSpace;
1646
0
    }
1647
0
}
1648
1649
void DOMLSSerializerImpl::release()
1650
0
{
1651
0
    DOMLSSerializerImpl* writer = (DOMLSSerializerImpl*) this;
1652
0
    delete writer;
1653
0
}
1654
1655
void DOMLSSerializerImpl::processBOM()
1656
0
{
1657
    // if the feature is not set, don't output bom
1658
0
    if (!getFeature(BYTE_ORDER_MARK_ID))
1659
0
        return;
1660
1661
0
    if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF8EncodingString)  == 0) ||
1662
0
        (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF8EncodingString2) == 0)  )
1663
0
    {
1664
0
        fFormatter->writeBOM(BOM_utf8, 3);
1665
0
    }
1666
0
    else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16LEncodingString)  == 0) ||
1667
0
        (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16LEncodingString2) == 0)  )
1668
0
    {
1669
0
        fFormatter->writeBOM(BOM_utf16le, 2);
1670
0
    }
1671
0
    else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16BEncodingString)  == 0) ||
1672
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16BEncodingString2) == 0)  )
1673
0
    {
1674
0
        fFormatter->writeBOM(BOM_utf16be, 2);
1675
0
    }
1676
0
    else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString)  == 0) ||
1677
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString2) == 0) ||
1678
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString3) == 0) ||
1679
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString4) == 0) ||
1680
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString5) == 0) ||
1681
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString6) == 0) ||
1682
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUTF16EncodingString7) == 0)  )
1683
0
    {
1684
0
        if (XMLPlatformUtils::fgXMLChBigEndian)
1685
0
            fFormatter->writeBOM(BOM_utf16be, 2);
1686
0
        else
1687
0
            fFormatter->writeBOM(BOM_utf16le, 2);
1688
0
    }
1689
0
    else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4LEncodingString)  == 0) ||
1690
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4LEncodingString2) == 0)  )
1691
0
    {
1692
0
        fFormatter->writeBOM(BOM_ucs4le, 4);
1693
0
    }
1694
0
    else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4BEncodingString)  == 0) ||
1695
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4BEncodingString2) == 0)  )
1696
0
    {
1697
0
        fFormatter->writeBOM(BOM_ucs4be, 4);
1698
0
    }
1699
0
    else if ((XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString)  == 0) ||
1700
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString2) == 0) ||
1701
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString3) == 0) ||
1702
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString4) == 0) ||
1703
0
             (XMLString::compareIStringASCII(fEncodingUsed, XMLUni::fgUCS4EncodingString5) == 0)  )
1704
0
    {
1705
0
        if (XMLPlatformUtils::fgXMLChBigEndian)
1706
0
            fFormatter->writeBOM(BOM_ucs4be, 4);
1707
0
        else
1708
0
            fFormatter->writeBOM(BOM_ucs4le, 4);
1709
0
    }
1710
0
}
1711
1712
bool DOMLSSerializerImpl::isDefaultNamespacePrefixDeclared() const
1713
0
{
1714
0
    for(XMLSize_t i=fNamespaceStack->size();i>0;i--)
1715
0
    {
1716
0
        RefHashTableOf<XMLCh>* curNamespaceMap=fNamespaceStack->elementAt(i-1);
1717
0
        const XMLCh* thisUri=curNamespaceMap->get((void*)XMLUni::fgZeroLenString);
1718
0
        if(thisUri)
1719
0
            return true;
1720
0
    }
1721
0
    return false;
1722
0
}
1723
1724
bool DOMLSSerializerImpl::isNamespaceBindingActive(const XMLCh* prefix, const XMLCh* uri) const
1725
0
{
1726
0
    for(XMLSize_t i=fNamespaceStack->size();i>0;i--)
1727
0
    {
1728
0
        RefHashTableOf<XMLCh>* curNamespaceMap=fNamespaceStack->elementAt(i-1);
1729
0
        const XMLCh* thisUri=curNamespaceMap->get((void*)prefix);
1730
        // if the prefix has been declared, check if it binds to the correct namespace, otherwise, reports it isn't bound
1731
0
        if(thisUri)
1732
0
            return XMLString::equals(thisUri,uri);
1733
0
    }
1734
0
    return false;
1735
0
}
1736
1737
void DOMLSSerializerImpl::ensureValidString(const DOMNode* nodeToWrite, const XMLCh* string)
1738
0
{
1739
    // XERCESC-1854: prevent illegal characters from being written
1740
    // XERCESC-2130: allow surrogates
1741
0
    if(string==0)
1742
0
        return;
1743
0
    const XMLCh* cursor=string;
1744
0
    while(*cursor!=0)
1745
0
    {
1746
0
        if((fIsXml11 && !XMLChar1_1::isXMLChar(*cursor)) || (!fIsXml11 && !XMLChar1_0::isXMLChar(*cursor)))
1747
0
        {
1748
0
            if((*cursor >= 0xD800) && (*cursor <= 0xDBFF))
1749
0
            {
1750
0
                XMLCh leadingSurrogate = *cursor;
1751
0
                cursor++;
1752
0
                if(0==*cursor || (fIsXml11 && !XMLChar1_1::isXMLChar(leadingSurrogate, *cursor)) || (!fIsXml11 && !XMLChar1_0::isXMLChar(leadingSurrogate, *cursor)))
1753
0
                {
1754
0
                    reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, XMLDOMMsg::INVALID_CHARACTER_ERR);
1755
0
                    return; // leave if reportError does not throw
1756
0
                }
1757
0
            }
1758
0
            else
1759
0
            {
1760
0
                reportError(nodeToWrite, DOMError::DOM_SEVERITY_FATAL_ERROR, XMLDOMMsg::INVALID_CHARACTER_ERR);
1761
0
            }
1762
0
        }
1763
0
        cursor++;
1764
0
    }
1765
0
}
1766
1767
XERCES_CPP_NAMESPACE_END