1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 #include <string.h> 24 25 #include <com/sun/star/lang/XServiceInfo.hpp> 26 #include <com/sun/star/util/XCloneable.hpp> 27 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> 28 #include <com/sun/star/xml/sax/XParser.hpp> 29 #include <com/sun/star/xml/sax/SAXParseException.hpp> 30 #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp> 31 32 #include <com/sun/star/io/XActiveDataSource.hpp> 33 34 #include <cppuhelper/factory.hxx> 35 #include <cppuhelper/weak.hxx> 36 #include <cppuhelper/implbase3.hxx> 37 38 #include <rtl/strbuf.hxx> 39 #include <rtl/byteseq.hxx> 40 #include <rtl/ustrbuf.hxx> 41 42 using namespace ::rtl; 43 using namespace ::std; 44 using namespace ::osl; 45 using namespace ::cppu; 46 using namespace ::com::sun::star::uno; 47 using namespace ::com::sun::star::lang; 48 using namespace ::com::sun::star::registry; 49 using namespace ::com::sun::star::xml::sax; 50 using namespace ::com::sun::star::util; 51 using namespace ::com::sun::star::io; 52 53 #include "factory.hxx" 54 #include "xml2utf.hxx" 55 56 #define LINEFEED 10 57 #define SEQUENCESIZE 1024 58 #define MAXCOLUMNCOUNT 72 59 60 /****** 61 * 62 * 63 * Character conversion functions 64 * 65 * 66 *****/ 67 68 namespace sax_expatwrap { 69 /***** 70 * 71 * Calculates the length of the sequence after conversion, but the conversion is not done. 72 * .g. &<>"' plus some more are 73 * special characters in XML that need to be transformed 74 * 75 * @param bConvertAll For Attributes it is necessary to convert every symbol (including line feed and tab) 76 * Set this to true, if you want to perform this special conversion 77 * @return The returned value is equal to the length of the incoming sequence, when no 78 + conversion is necessary, otherwise it is larger than the length of the sequence. 79 ****/ 80 // inline sal_Int32 CalcXMLLen( const Sequence<sal_Int8> & seq , sal_Bool bConvertAll ) throw() 81 // { 82 // sal_Int32 nLen = 0; 83 // const sal_Int8 *pArray = seq.getConstArray(); 84 85 // for( int i = 0 ; i < seq.getLength() ; i ++ ) { 86 87 // sal_Int8 c = pArray[i]; 88 // switch( c ) 89 // { 90 // case '&': // resemble to & 91 // nLen +=5; 92 // break; 93 // case '<': // < 94 // case '>': // > 95 // nLen +=4; 96 // break; 97 // case 39: // 39 == ''', ' 98 // case '"': // " 99 // case 13: // 
 100 // nLen += 6; 101 // break; 102 103 // case 10: // 
 104 // case 9: // 	 105 // if( bConvertAll ) 106 // { 107 // nLen += 6; // 108 // } 109 // break; 110 // default: 111 // nLen ++; 112 // } 113 // } 114 115 // return nLen; 116 // } 117 118 enum SaxInvalidCharacterError 119 { 120 SAX_NONE, 121 SAX_WARNING, 122 SAX_ERROR 123 }; 124 125 class SaxWriterHelper 126 { 127 Reference< XOutputStream > m_out; 128 Sequence < sal_Int8 > m_Sequence; 129 sal_Int8* mp_Sequence; 130 131 sal_Int32 nLastLineFeedPos; // is negative after writing a sequence 132 sal_uInt32 nCurrentPos; 133 sal_Bool m_bStartElementFinished; 134 135 136 inline sal_uInt32 writeSequence() throw( SAXException ); 137 138 // use only if to insert the bytes more space in the sequence is needed and 139 // so the sequence has to write out and reset rPos to 0 140 // writes sequence only on overflow, sequence could be full on the end (rPos == SEQUENCESIZE) 141 inline void AddBytes(sal_Int8* pTarget, sal_uInt32& rPos, 142 const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException ); 143 inline sal_Bool convertToXML(const sal_Unicode * pStr, 144 sal_Int32 nStrLen, 145 sal_Bool bDoNormalization, 146 sal_Bool bNormalizeWhitespace, 147 sal_Int8 *pTarget, 148 sal_uInt32& rPos) throw( SAXException ); 149 inline void FinishStartElement() throw( SAXException ); 150 public: 151 SaxWriterHelper(Reference< XOutputStream > m_TempOut) : 152 m_out(m_TempOut), 153 m_Sequence(SEQUENCESIZE), 154 mp_Sequence(NULL), 155 nLastLineFeedPos(0), 156 nCurrentPos(0), 157 m_bStartElementFinished(sal_True) 158 { 159 OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small"); 160 mp_Sequence = m_Sequence.getArray(); 161 } 162 ~SaxWriterHelper() 163 { 164 OSL_ENSURE(!nCurrentPos, "cached Sequence not written"); 165 OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written"); 166 } 167 168 inline void insertIndentation(sal_uInt32 m_nLevel) throw( SAXException ); 169 170 // returns whether it works correct or invalid characters were in the string 171 // If there are invalid characters in the string it returns sal_False. 172 // Than the calling method has to throw the needed Exception. 173 inline sal_Bool writeString(const rtl::OUString& rWriteOutString, 174 sal_Bool bDoNormalization, 175 sal_Bool bNormalizeWhitespace) throw( SAXException ); 176 177 sal_uInt32 GetLastColumnCount() { return (sal_uInt32)(nCurrentPos - nLastLineFeedPos); } 178 179 inline void startDocument() throw( SAXException ); 180 181 // returns whether it works correct or invalid characters were in the strings 182 // If there are invalid characters in one of the strings it returns sal_False. 183 // Than the calling method has to throw the needed Exception. 184 inline SaxInvalidCharacterError startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException ); 185 inline sal_Bool FinishEmptyElement() throw( SAXException ); 186 187 // returns whether it works correct or invalid characters were in the string 188 // If there are invalid characters in the string it returns sal_False. 189 // Than the calling method has to throw the needed Exception. 190 inline sal_Bool endElement(const rtl::OUString& rName) throw( SAXException ); 191 inline void endDocument() throw( SAXException ); 192 193 // returns whether it works correct or invalid characters were in the strings 194 // If there are invalid characters in the string it returns sal_False. 195 // Than the calling method has to throw the needed Exception. 196 inline sal_Bool processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException ); 197 inline void startCDATA() throw( SAXException ); 198 inline void endCDATA() throw( SAXException ); 199 200 // returns whether it works correct or invalid characters were in the strings 201 // If there are invalid characters in the string it returns sal_False. 202 // Than the calling method has to throw the needed Exception. 203 inline sal_Bool comment(const rtl::OUString& rComment) throw( SAXException ); 204 205 inline void clearBuffer() throw( SAXException ); 206 }; 207 208 const sal_Bool g_bValidCharsBelow32[32] = 209 { 210 // 0 1 2 3 4 5 6 7 211 0,0,0,0,0,0,0,0, //0 212 0,1,1,0,0,1,0,0, //8 213 0,0,0,0,0,0,0,0, //16 214 0,0,0,0,0,0,0,0 215 }; 216 217 inline sal_Bool IsInvalidChar(const sal_Unicode aChar) 218 { 219 sal_Bool bRet(sal_False); 220 // check first for the most common characters 221 if( aChar < 32 || aChar >= 0xd800 ) 222 bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) || 223 aChar == 0xffff || 224 aChar == 0xfffe ); 225 return bRet; 226 } 227 228 /******** 229 * write through to the output stream 230 * 231 *****/ 232 inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException ) 233 { 234 try 235 { 236 m_out->writeBytes( m_Sequence ); 237 } 238 catch( IOException & e ) 239 { 240 Any a; 241 a <<= e; 242 throw SAXException( 243 OUString::createFromAscii( "io exception during writing" ), 244 Reference< XInterface > (), 245 a ); 246 } 247 nLastLineFeedPos -= SEQUENCESIZE; 248 return 0; 249 } 250 251 inline void SaxWriterHelper::AddBytes(sal_Int8* pTarget, sal_uInt32& rPos, 252 const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException ) 253 { 254 OSL_ENSURE((rPos + nBytesCount) > SEQUENCESIZE, "wrong use of AddBytesMethod"); 255 sal_uInt32 nCount(SEQUENCESIZE - rPos); 256 memcpy( &(pTarget[rPos]) , pBytes, nCount); 257 258 OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end"); 259 260 rPos = writeSequence(); 261 sal_uInt32 nRestCount(nBytesCount - nCount); 262 if ((rPos + nRestCount) <= SEQUENCESIZE) 263 { 264 memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount); 265 rPos += nRestCount; 266 } 267 else 268 AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount); 269 } 270 271 /** Converts an UTF16 string to UTF8 and does XML normalization 272 273 @param pTarget 274 Pointer to a piece of memory, to where the output should be written. The caller 275 must call calcXMLByteLength on the same string, to ensure, 276 that there is enough memory for converting. 277 */ 278 inline sal_Bool SaxWriterHelper::convertToXML( const sal_Unicode * pStr, 279 sal_Int32 nStrLen, 280 sal_Bool bDoNormalization, 281 sal_Bool bNormalizeWhitespace, 282 sal_Int8 *pTarget, 283 sal_uInt32& rPos ) throw( SAXException ) 284 { 285 sal_Bool bRet(sal_True); 286 sal_uInt32 nSurrogate = 0; 287 288 for( sal_Int32 i = 0 ; i < nStrLen ; i ++ ) 289 { 290 sal_uInt16 c = pStr[i]; 291 if (IsInvalidChar(c)) 292 bRet = sal_False; 293 else if( (c >= 0x0001) && (c <= 0x007F) ) 294 { 295 if( bDoNormalization ) 296 { 297 switch( c ) 298 { 299 case '&': // resemble to & 300 { 301 if ((rPos + 5) > SEQUENCESIZE) 302 AddBytes(pTarget, rPos, (sal_Int8*)"&", 5); 303 else 304 { 305 memcpy( &(pTarget[rPos]) , "&", 5 ); 306 rPos += 5; 307 } 308 } 309 break; 310 case '<': 311 { 312 if ((rPos + 4) > SEQUENCESIZE) 313 AddBytes(pTarget, rPos, (sal_Int8*)"<", 4); 314 else 315 { 316 memcpy( &(pTarget[rPos]) , "<" , 4 ); 317 rPos += 4; // < 318 } 319 } 320 break; 321 case '>': 322 { 323 if ((rPos + 4) > SEQUENCESIZE) 324 AddBytes(pTarget, rPos, (sal_Int8*)">", 4); 325 else 326 { 327 memcpy( &(pTarget[rPos]) , ">" , 4 ); 328 rPos += 4; // > 329 } 330 } 331 break; 332 case 39: // 39 == ''' 333 { 334 if ((rPos + 6) > SEQUENCESIZE) 335 AddBytes(pTarget, rPos, (sal_Int8*)"'", 6); 336 else 337 { 338 memcpy( &(pTarget[rPos]) , "'" , 6 ); 339 rPos += 6; // ' 340 } 341 } 342 break; 343 case '"': 344 { 345 if ((rPos + 6) > SEQUENCESIZE) 346 AddBytes(pTarget, rPos, (sal_Int8*)""", 6); 347 else 348 { 349 memcpy( &(pTarget[rPos]) , """ , 6 ); 350 rPos += 6; // " 351 } 352 } 353 break; 354 case 13: 355 { 356 if ((rPos + 6) > SEQUENCESIZE) 357 AddBytes(pTarget, rPos, (sal_Int8*)"
", 6); 358 else 359 { 360 memcpy( &(pTarget[rPos]) , "
" , 6 ); 361 rPos += 6; 362 } 363 } 364 break; 365 case LINEFEED: 366 { 367 if( bNormalizeWhitespace ) 368 { 369 if ((rPos + 6) > SEQUENCESIZE) 370 AddBytes(pTarget, rPos, (sal_Int8*)"
" , 6); 371 else 372 { 373 memcpy( &(pTarget[rPos]) , "
" , 6 ); 374 rPos += 6; 375 } 376 } 377 else 378 { 379 pTarget[rPos] = LINEFEED; 380 nLastLineFeedPos = rPos; 381 rPos ++; 382 } 383 } 384 break; 385 case 9: 386 { 387 if( bNormalizeWhitespace ) 388 { 389 if ((rPos + 6) > SEQUENCESIZE) 390 AddBytes(pTarget, rPos, (sal_Int8*)"	" , 6); 391 else 392 { 393 memcpy( &(pTarget[rPos]) , "	" , 6 ); 394 rPos += 6; 395 } 396 } 397 else 398 { 399 pTarget[rPos] = 9; 400 rPos ++; 401 } 402 } 403 break; 404 default: 405 { 406 pTarget[rPos] = (sal_Int8)c; 407 rPos ++; 408 } 409 break; 410 } 411 } 412 else 413 { 414 pTarget[rPos] = (sal_Int8)c; 415 if ((sal_Int8)c == LINEFEED) 416 nLastLineFeedPos = rPos; 417 rPos ++; 418 } 419 } 420 else if( c >= 0xd800 && c < 0xdc00 ) 421 { 422 // 1. surrogate: save (until 2. surrogate) 423 OSL_ENSURE( nSurrogate == 0, "left-over Unicode surrogate" ); 424 nSurrogate = ( ( c & 0x03ff ) + 0x0040 ); 425 } 426 else if( c >= 0xdc00 && c < 0xe000 ) 427 { 428 // 2. surrogate: write as UTF-8 429 OSL_ENSURE( nSurrogate != 0, "lone 2nd Unicode surrogate" ); 430 431 nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff ); 432 if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF ) 433 { 434 sal_Int8 aBytes[] = { sal_Int8(0xF0 | ((nSurrogate >> 18) & 0x0F)), 435 sal_Int8(0x80 | ((nSurrogate >> 12) & 0x3F)), 436 sal_Int8(0x80 | ((nSurrogate >> 6) & 0x3F)), 437 sal_Int8(0x80 | ((nSurrogate >> 0) & 0x3F)) }; 438 if ((rPos + 4) > SEQUENCESIZE) 439 AddBytes(pTarget, rPos, aBytes, 4); 440 else 441 { 442 pTarget[rPos] = aBytes[0]; 443 rPos ++; 444 pTarget[rPos] = aBytes[1]; 445 rPos ++; 446 pTarget[rPos] = aBytes[2]; 447 rPos ++; 448 pTarget[rPos] = aBytes[3]; 449 rPos ++; 450 } 451 } 452 else 453 { 454 OSL_ENSURE( false, "illegal Unicode character" ); 455 bRet = sal_False; 456 } 457 458 // reset surrogate 459 nSurrogate = 0; 460 } 461 else if( c > 0x07FF ) 462 { 463 sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)), 464 sal_Int8(0x80 | ((c >> 6) & 0x3F)), 465 sal_Int8(0x80 | ((c >> 0) & 0x3F)) }; 466 if ((rPos + 3) > SEQUENCESIZE) 467 AddBytes(pTarget, rPos, aBytes, 3); 468 else 469 { 470 pTarget[rPos] = aBytes[0]; 471 rPos ++; 472 pTarget[rPos] = aBytes[1]; 473 rPos ++; 474 pTarget[rPos] = aBytes[2]; 475 rPos ++; 476 } 477 } 478 else 479 { 480 sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >> 6) & 0x1F)), 481 sal_Int8(0x80 | ((c >> 0) & 0x3F)) }; 482 if ((rPos + 2) > SEQUENCESIZE) 483 AddBytes(pTarget, rPos, aBytes, 2); 484 else 485 { 486 pTarget[rPos] = aBytes[0]; 487 rPos ++; 488 pTarget[rPos] = aBytes[1]; 489 rPos ++; 490 } 491 } 492 OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position"); 493 if (rPos == SEQUENCESIZE) 494 rPos = writeSequence(); 495 496 // reset left-over surrogate 497 if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) ) 498 { 499 OSL_ENSURE( nSurrogate != 0, "left-over Unicode surrogate" ); 500 nSurrogate = 0; 501 bRet = sal_False; 502 } 503 } 504 return bRet; 505 } 506 507 inline void SaxWriterHelper::FinishStartElement() throw( SAXException ) 508 { 509 if (!m_bStartElementFinished) 510 { 511 mp_Sequence[nCurrentPos] = '>'; 512 nCurrentPos++; 513 if (nCurrentPos == SEQUENCESIZE) 514 nCurrentPos = writeSequence(); 515 m_bStartElementFinished = sal_True; 516 } 517 } 518 519 inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException ) 520 { 521 FinishStartElement(); 522 if (m_nLevel > 0) 523 { 524 if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE) 525 { 526 mp_Sequence[nCurrentPos] = LINEFEED; 527 nLastLineFeedPos = nCurrentPos; 528 nCurrentPos++; 529 memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel ); 530 nCurrentPos += m_nLevel; 531 if (nCurrentPos == SEQUENCESIZE) 532 nCurrentPos = writeSequence(); 533 } 534 else 535 { 536 sal_uInt32 nCount(m_nLevel + 1); 537 sal_Int8* pBytes = new sal_Int8[nCount]; 538 pBytes[0] = LINEFEED; 539 memset( &(pBytes[1]), 32, m_nLevel ); 540 AddBytes(mp_Sequence, nCurrentPos, pBytes, nCount); 541 delete[] pBytes; 542 nLastLineFeedPos = nCurrentPos - nCount; 543 if (nCurrentPos == SEQUENCESIZE) 544 nCurrentPos = writeSequence(); 545 } 546 } 547 else 548 { 549 mp_Sequence[nCurrentPos] = LINEFEED; 550 nLastLineFeedPos = nCurrentPos; 551 nCurrentPos++; 552 if (nCurrentPos == SEQUENCESIZE) 553 nCurrentPos = writeSequence(); 554 } 555 } 556 557 inline sal_Bool SaxWriterHelper::writeString( const rtl::OUString& rWriteOutString, 558 sal_Bool bDoNormalization, 559 sal_Bool bNormalizeWhitespace ) throw( SAXException ) 560 { 561 FinishStartElement(); 562 return convertToXML(rWriteOutString.getStr(), 563 rWriteOutString.getLength(), 564 bDoNormalization, 565 bNormalizeWhitespace, 566 mp_Sequence, 567 nCurrentPos); 568 } 569 570 inline void SaxWriterHelper::startDocument() throw( SAXException ) 571 { 572 const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; 573 const int nLen = strlen( pc ); 574 if ((nCurrentPos + nLen) <= SEQUENCESIZE) 575 { 576 memcpy( mp_Sequence, pc , nLen ); 577 nCurrentPos += nLen; 578 } 579 else 580 { 581 AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)pc, nLen); 582 } 583 OSL_ENSURE(nCurrentPos <= SEQUENCESIZE, "not reset current position"); 584 if (nCurrentPos == SEQUENCESIZE) 585 nCurrentPos = writeSequence(); 586 mp_Sequence[nCurrentPos] = LINEFEED; 587 nCurrentPos++; 588 if (nCurrentPos == SEQUENCESIZE) 589 nCurrentPos = writeSequence(); 590 } 591 592 inline SaxInvalidCharacterError SaxWriterHelper::startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException ) 593 { 594 FinishStartElement(); 595 mp_Sequence[nCurrentPos] = '<'; 596 nCurrentPos++; 597 if (nCurrentPos == SEQUENCESIZE) 598 nCurrentPos = writeSequence(); 599 600 SaxInvalidCharacterError eRet(SAX_NONE); 601 if (!writeString(rName, sal_False, sal_False)) 602 eRet = SAX_ERROR; 603 604 sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0; 605 for(sal_Int16 i = 0 ; i < nAttribCount ; i++ ) 606 { 607 mp_Sequence[nCurrentPos] = ' '; 608 nCurrentPos++; 609 if (nCurrentPos == SEQUENCESIZE) 610 nCurrentPos = writeSequence(); 611 612 if (!writeString(xAttribs->getNameByIndex( i ), sal_False, sal_False)) 613 eRet = SAX_ERROR; 614 615 mp_Sequence[nCurrentPos] = '='; 616 nCurrentPos++; 617 if (nCurrentPos == SEQUENCESIZE) 618 nCurrentPos = writeSequence(); 619 mp_Sequence[nCurrentPos] = '"'; 620 nCurrentPos++; 621 if (nCurrentPos == SEQUENCESIZE) 622 nCurrentPos = writeSequence(); 623 624 if (!writeString(xAttribs->getValueByIndex( i ), sal_True, sal_True) && 625 !(eRet == SAX_ERROR)) 626 eRet = SAX_WARNING; 627 628 mp_Sequence[nCurrentPos] = '"'; 629 nCurrentPos++; 630 if (nCurrentPos == SEQUENCESIZE) 631 nCurrentPos = writeSequence(); 632 } 633 634 m_bStartElementFinished = sal_False; // because the '>' character is not added, 635 // because it is possible, that the "/>" 636 // characters have to add 637 return eRet; 638 } 639 640 inline sal_Bool SaxWriterHelper::FinishEmptyElement() throw( SAXException ) 641 { 642 if (m_bStartElementFinished) 643 return sal_False; 644 645 mp_Sequence[nCurrentPos] = '/'; 646 nCurrentPos++; 647 if (nCurrentPos == SEQUENCESIZE) 648 nCurrentPos = writeSequence(); 649 mp_Sequence[nCurrentPos] = '>'; 650 nCurrentPos++; 651 if (nCurrentPos == SEQUENCESIZE) 652 nCurrentPos = writeSequence(); 653 654 m_bStartElementFinished = sal_True; 655 656 return sal_True; 657 } 658 659 inline sal_Bool SaxWriterHelper::endElement(const rtl::OUString& rName) throw( SAXException ) 660 { 661 FinishStartElement(); 662 mp_Sequence[nCurrentPos] = '<'; 663 nCurrentPos++; 664 if (nCurrentPos == SEQUENCESIZE) 665 nCurrentPos = writeSequence(); 666 mp_Sequence[nCurrentPos] = '/'; 667 nCurrentPos++; 668 if (nCurrentPos == SEQUENCESIZE) 669 nCurrentPos = writeSequence(); 670 671 sal_Bool bRet(writeString( rName, sal_False, sal_False)); 672 673 mp_Sequence[nCurrentPos] = '>'; 674 nCurrentPos++; 675 if (nCurrentPos == SEQUENCESIZE) 676 nCurrentPos = writeSequence(); 677 678 return bRet; 679 } 680 681 inline void SaxWriterHelper::endDocument() throw( SAXException ) 682 { 683 if (nCurrentPos > 0) 684 { 685 m_Sequence.realloc(nCurrentPos); 686 nCurrentPos = writeSequence(); 687 //m_Sequence.realloc(SEQUENCESIZE); 688 } 689 } 690 691 inline void SaxWriterHelper::clearBuffer() throw( SAXException ) 692 { 693 FinishStartElement(); 694 if (nCurrentPos > 0) 695 { 696 m_Sequence.realloc(nCurrentPos); 697 nCurrentPos = writeSequence(); 698 m_Sequence.realloc(SEQUENCESIZE); 699 // Be sure to update the array pointer after the reallocation. 700 mp_Sequence = m_Sequence.getArray(); 701 } 702 } 703 704 inline sal_Bool SaxWriterHelper::processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException ) 705 { 706 FinishStartElement(); 707 mp_Sequence[nCurrentPos] = '<'; 708 nCurrentPos++; 709 if (nCurrentPos == SEQUENCESIZE) 710 nCurrentPos = writeSequence(); 711 mp_Sequence[nCurrentPos] = '?'; 712 nCurrentPos++; 713 if (nCurrentPos == SEQUENCESIZE) 714 nCurrentPos = writeSequence(); 715 716 sal_Bool bRet(writeString( rTarget, sal_False, sal_False )); 717 718 mp_Sequence[nCurrentPos] = ' '; 719 nCurrentPos++; 720 if (nCurrentPos == SEQUENCESIZE) 721 nCurrentPos = writeSequence(); 722 723 if (!writeString( rData, sal_False, sal_False )) 724 bRet = sal_False; 725 726 mp_Sequence[nCurrentPos] = '?'; 727 nCurrentPos++; 728 if (nCurrentPos == SEQUENCESIZE) 729 nCurrentPos = writeSequence(); 730 mp_Sequence[nCurrentPos] = '>'; 731 nCurrentPos++; 732 if (nCurrentPos == SEQUENCESIZE) 733 nCurrentPos = writeSequence(); 734 735 return bRet; 736 } 737 738 inline void SaxWriterHelper::startCDATA() throw( SAXException ) 739 { 740 FinishStartElement(); 741 if ((nCurrentPos + 9) <= SEQUENCESIZE) 742 { 743 memcpy( &(mp_Sequence[nCurrentPos]), "<![CDATA[" , 9 ); 744 nCurrentPos += 9; 745 } 746 else 747 AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"<![CDATA[" , 9); 748 if (nCurrentPos == SEQUENCESIZE) 749 nCurrentPos = writeSequence(); 750 } 751 752 inline void SaxWriterHelper::endCDATA() throw( SAXException ) 753 { 754 FinishStartElement(); 755 if ((nCurrentPos + 3) <= SEQUENCESIZE) 756 { 757 memcpy( &(mp_Sequence[nCurrentPos]), "]]>" , 3 ); 758 nCurrentPos += 3; 759 } 760 else 761 AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"]]>" , 3); 762 if (nCurrentPos == SEQUENCESIZE) 763 nCurrentPos = writeSequence(); 764 } 765 766 inline sal_Bool SaxWriterHelper::comment(const rtl::OUString& rComment) throw( SAXException ) 767 { 768 FinishStartElement(); 769 mp_Sequence[nCurrentPos] = '<'; 770 nCurrentPos++; 771 if (nCurrentPos == SEQUENCESIZE) 772 nCurrentPos = writeSequence(); 773 mp_Sequence[nCurrentPos] = '!'; 774 nCurrentPos++; 775 if (nCurrentPos == SEQUENCESIZE) 776 nCurrentPos = writeSequence(); 777 mp_Sequence[nCurrentPos] = '-'; 778 nCurrentPos++; 779 if (nCurrentPos == SEQUENCESIZE) 780 nCurrentPos = writeSequence(); 781 mp_Sequence[nCurrentPos] = '-'; 782 nCurrentPos++; 783 if (nCurrentPos == SEQUENCESIZE) 784 nCurrentPos = writeSequence(); 785 786 sal_Bool bRet(writeString( rComment, sal_False, sal_False)); 787 788 mp_Sequence[nCurrentPos] = '-'; 789 nCurrentPos++; 790 if (nCurrentPos == SEQUENCESIZE) 791 nCurrentPos = writeSequence(); 792 mp_Sequence[nCurrentPos] = '-'; 793 nCurrentPos++; 794 if (nCurrentPos == SEQUENCESIZE) 795 nCurrentPos = writeSequence(); 796 mp_Sequence[nCurrentPos] = '>'; 797 nCurrentPos++; 798 if (nCurrentPos == SEQUENCESIZE) 799 nCurrentPos = writeSequence(); 800 801 return bRet; 802 } 803 804 inline sal_Int32 calcXMLByteLength( const sal_Unicode *pStr, sal_Int32 nStrLen, 805 sal_Bool bDoNormalization, 806 sal_Bool bNormalizeWhitespace ) 807 { 808 sal_Int32 nOutputLength = 0; 809 sal_uInt32 nSurrogate = 0; 810 811 for( sal_Int32 i = 0 ; i < nStrLen ; i++ ) 812 { 813 sal_uInt16 c = pStr[i]; 814 if( !IsInvalidChar(c) && (c >= 0x0001) && (c <= 0x007F) ) 815 { 816 if( bDoNormalization ) 817 { 818 switch( c ) 819 { 820 case '&': // resemble to & 821 nOutputLength +=5; 822 break; 823 case '<': // < 824 case '>': // > 825 nOutputLength +=4; 826 break; 827 case 39: // 39 == ''', ' 828 case '"': // " 829 case 13: // 
 830 nOutputLength += 6; 831 break; 832 833 case 10: // 
 834 case 9: // 	 835 if( bNormalizeWhitespace ) 836 { 837 nOutputLength += 6; // 838 } 839 else 840 { 841 nOutputLength ++; 842 } 843 break; 844 default: 845 nOutputLength ++; 846 } 847 } 848 else 849 { 850 nOutputLength ++; 851 } 852 } 853 else if( c >= 0xd800 && c < 0xdc00 ) 854 { 855 // save surrogate 856 nSurrogate = ( ( c & 0x03ff ) + 0x0040 ); 857 } 858 else if( c >= 0xdc00 && c < 0xe000 ) 859 { 860 // 2. surrogate: write as UTF-8 (if range is OK 861 nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff ); 862 if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF ) 863 nOutputLength += 4; 864 nSurrogate = 0; 865 } 866 else if( c > 0x07FF ) 867 { 868 nOutputLength += 3; 869 } 870 else 871 { 872 nOutputLength += 2; 873 } 874 875 // surrogate processing 876 if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) ) 877 nSurrogate = 0; 878 } 879 880 return nOutputLength; 881 } 882 883 /** returns position of first ascii 10 within the string, -1 when no 10 in string. 884 */ 885 static inline sal_Int32 getFirstLineBreak( const OUString & str ) throw () 886 { 887 const sal_Unicode *pSource = str.getStr(); 888 sal_Int32 nLen = str.getLength(); 889 890 for( int n = 0; n < nLen ; n ++ ) 891 { 892 if( LINEFEED == pSource[n] ) { 893 return n; 894 } 895 } 896 return -1; 897 } 898 899 /** returns position of last ascii 10 within sequence, -1 when no 10 in string. 900 */ 901 static inline sal_Int32 getLastLineBreak( const Sequence<sal_Int8> & seq) throw () 902 { 903 const sal_Int8 *pSource = seq.getConstArray(); 904 sal_Int32 nLen = seq.getLength(); 905 906 for( int n = nLen-1; n >= 0 ; n -- ) 907 { 908 if( LINEFEED == pSource[n] ) { 909 return n; 910 } 911 } 912 return -1; 913 } 914 915 916 class SAXWriter : 917 public WeakImplHelper3< 918 XActiveDataSource, 919 XExtendedDocumentHandler, 920 XServiceInfo > 921 { 922 public: 923 SAXWriter( ) : 924 m_seqStartElement(), 925 mp_SaxWriterHelper( NULL ), 926 m_bForceLineBreak(sal_False), 927 m_bAllowLineBreak(sal_False) 928 {} 929 ~SAXWriter() 930 { 931 delete mp_SaxWriterHelper; 932 } 933 934 public: // XActiveDataSource 935 virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream) 936 throw (RuntimeException) 937 { 938 // temporary: set same stream again to clear buffer 939 if ( m_out == aStream && mp_SaxWriterHelper && m_bDocStarted ) 940 mp_SaxWriterHelper->clearBuffer(); 941 else 942 { 943 944 m_out = aStream; 945 delete mp_SaxWriterHelper; 946 mp_SaxWriterHelper = new SaxWriterHelper(m_out); 947 m_bDocStarted = sal_False; 948 m_nLevel = 0; 949 m_bIsCDATA = sal_False; 950 951 } 952 } 953 virtual Reference< XOutputStream > SAL_CALL getOutputStream(void) 954 throw(RuntimeException) 955 { return m_out; } 956 957 public: // XDocumentHandler 958 virtual void SAL_CALL startDocument(void) 959 throw(SAXException, RuntimeException); 960 961 virtual void SAL_CALL endDocument(void) 962 throw(SAXException, RuntimeException); 963 964 virtual void SAL_CALL startElement(const OUString& aName, 965 const Reference< XAttributeList > & xAttribs) 966 throw (SAXException, RuntimeException); 967 968 virtual void SAL_CALL endElement(const OUString& aName) 969 throw(SAXException, RuntimeException); 970 971 virtual void SAL_CALL characters(const OUString& aChars) 972 throw(SAXException, RuntimeException); 973 974 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) 975 throw(SAXException, RuntimeException); 976 virtual void SAL_CALL processingInstruction(const OUString& aTarget, 977 const OUString& aData) 978 throw(SAXException, RuntimeException); 979 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator) 980 throw(SAXException, RuntimeException); 981 982 public: // XExtendedDocumentHandler 983 virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException); 984 virtual void SAL_CALL endCDATA(void) throw(RuntimeException); 985 virtual void SAL_CALL comment(const OUString& sComment) 986 throw(SAXException, RuntimeException); 987 virtual void SAL_CALL unknown(const OUString& sString) 988 throw(SAXException, RuntimeException); 989 virtual void SAL_CALL allowLineBreak(void) 990 throw(SAXException,RuntimeException); 991 992 public: // XServiceInfo 993 OUString SAL_CALL getImplementationName() throw(); 994 Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(); 995 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(); 996 997 private: 998 999 void writeSequence( const Sequence<sal_Int8> & seq ); 1000 sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw(); 1001 1002 Reference< XOutputStream > m_out; 1003 Sequence < sal_Int8 > m_seqStartElement; 1004 SaxWriterHelper* mp_SaxWriterHelper; 1005 1006 // Status information 1007 sal_Bool m_bDocStarted : 1; 1008 sal_Bool m_bIsCDATA : 1; 1009 sal_Bool m_bForceLineBreak : 1; 1010 sal_Bool m_bAllowLineBreak : 1; 1011 sal_Int32 m_nLevel; 1012 }; 1013 1014 1015 //-------------------------------------- 1016 // the extern interface 1017 //--------------------------------------- 1018 Reference < XInterface > SAL_CALL SaxWriter_CreateInstance( 1019 const Reference < XMultiServiceFactory > & ) 1020 throw (Exception) 1021 { 1022 SAXWriter *p = new SAXWriter; 1023 return Reference< XInterface > ( SAL_STATIC_CAST(OWeakObject *, p ) ); 1024 } 1025 1026 OUString SaxWriter_getServiceName() throw() 1027 { 1028 return OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ); 1029 } 1030 1031 OUString SaxWriter_getImplementationName() throw() 1032 { 1033 return OUString::createFromAscii( "com.sun.star.extensions.xml.sax.Writer" ); 1034 } 1035 1036 Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw() 1037 { 1038 Sequence<OUString> aRet(1); 1039 aRet.getArray()[0] = SaxWriter_getServiceName(); 1040 return aRet; 1041 } 1042 1043 1044 sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw() 1045 { 1046 sal_Int32 nLength =-1; 1047 if (mp_SaxWriterHelper) 1048 { 1049 if ( m_bForceLineBreak || 1050 (m_bAllowLineBreak && 1051 ((nFirstLineBreakOccurence + mp_SaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) ) 1052 nLength = m_nLevel; 1053 } 1054 m_bForceLineBreak = sal_False; 1055 m_bAllowLineBreak = sal_False; 1056 return nLength; 1057 } 1058 1059 static inline sal_Bool isFirstCharWhitespace( const sal_Unicode *p ) throw() 1060 { 1061 return *p == ' '; 1062 } 1063 1064 1065 // XServiceInfo 1066 OUString SAXWriter::getImplementationName() throw() 1067 { 1068 return SaxWriter_getImplementationName(); 1069 } 1070 1071 // XServiceInfo 1072 sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw() 1073 { 1074 Sequence< OUString > aSNL = getSupportedServiceNames(); 1075 const OUString * pArray = aSNL.getConstArray(); 1076 1077 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 1078 if( pArray[i] == ServiceName ) 1079 return sal_True; 1080 1081 return sal_False; 1082 } 1083 1084 // XServiceInfo 1085 Sequence< OUString > SAXWriter::getSupportedServiceNames(void) throw () 1086 { 1087 Sequence<OUString> seq(1); 1088 seq.getArray()[0] = SaxWriter_getServiceName(); 1089 return seq; 1090 } 1091 1092 1093 1094 void SAXWriter::startDocument() throw(SAXException, RuntimeException ) 1095 { 1096 if( m_bDocStarted || ! m_out.is() || !mp_SaxWriterHelper ) { 1097 throw SAXException(); 1098 } 1099 m_bDocStarted = sal_True; 1100 mp_SaxWriterHelper->startDocument(); 1101 } 1102 1103 1104 void SAXWriter::endDocument(void) throw(SAXException, RuntimeException) 1105 { 1106 if( ! m_bDocStarted ) 1107 { 1108 throw SAXException( 1109 OUString::createFromAscii( "endDocument called before startDocument" ), 1110 Reference< XInterface >() , Any() ); 1111 } 1112 if( m_nLevel ) { 1113 throw SAXException( 1114 OUString::createFromAscii( "unexpected end of document" ), 1115 Reference< XInterface >() , Any() ); 1116 } 1117 mp_SaxWriterHelper->endDocument(); 1118 try 1119 { 1120 m_out->closeOutput(); 1121 } 1122 catch( IOException & e ) 1123 { 1124 Any a; 1125 a <<= e; 1126 throw SAXException( 1127 OUString::createFromAscii( "IO exception during closing the IO Stream" ), 1128 Reference< XInterface > (), 1129 a ); 1130 } 1131 } 1132 1133 1134 void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs) 1135 throw(SAXException, RuntimeException) 1136 { 1137 if( ! m_bDocStarted ) 1138 { 1139 SAXException except; 1140 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement called before startDocument" )); 1141 throw except; 1142 } 1143 if( m_bIsCDATA ) 1144 { 1145 SAXException except; 1146 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement call not allowed with CDATA sections" )); 1147 throw except; 1148 } 1149 1150 sal_Int32 nLength(0); 1151 if (m_bAllowLineBreak) 1152 { 1153 sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0; 1154 1155 nLength ++; // "<" 1156 nLength += calcXMLByteLength( aName.getStr() , aName.getLength(), 1157 sal_False, sal_False ); // the tag name 1158 1159 sal_Int16 n; 1160 for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) { 1161 nLength ++; // " " 1162 OUString tmp = xAttribs->getNameByIndex( n ); 1163 1164 nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , sal_False, sal_False ); 1165 1166 nLength += 2; // =" 1167 1168 tmp = xAttribs->getValueByIndex( n ); 1169 1170 nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), sal_True, sal_True ); 1171 1172 nLength += 1; // " 1173 } 1174 1175 nLength ++; // '>' 1176 } 1177 1178 // Is there a new indentation necesarry ? 1179 sal_Int32 nPrefix(getIndentPrefixLength( nLength )); 1180 1181 // write into sequence 1182 if( nPrefix >= 0 ) 1183 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1184 1185 SaxInvalidCharacterError eRet(mp_SaxWriterHelper->startElement(aName, xAttribs)); 1186 1187 m_nLevel++; 1188 1189 if (eRet == SAX_WARNING) 1190 { 1191 SAXInvalidCharacterException except; 1192 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export in a attribute value" ) ); 1193 throw except; 1194 } 1195 else if (eRet == SAX_ERROR) 1196 { 1197 SAXException except; 1198 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1199 throw except; 1200 } 1201 } 1202 1203 void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException) 1204 { 1205 if( ! m_bDocStarted ) { 1206 throw SAXException (); 1207 } 1208 m_nLevel --; 1209 1210 if( m_nLevel < 0 ) { 1211 throw SAXException(); 1212 } 1213 sal_Bool bRet(sal_True); 1214 1215 if( mp_SaxWriterHelper->FinishEmptyElement() ) 1216 m_bForceLineBreak = sal_False; 1217 else 1218 { 1219 // only ascii chars allowed 1220 sal_Int32 nLength(0); 1221 if (m_bAllowLineBreak) 1222 nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), sal_False, sal_False ); 1223 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1224 1225 if( nPrefix >= 0 ) 1226 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1227 1228 bRet = mp_SaxWriterHelper->endElement(aName); 1229 } 1230 1231 if (!bRet) 1232 { 1233 SAXException except; 1234 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1235 throw except; 1236 } 1237 } 1238 1239 void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException) 1240 { 1241 if( ! m_bDocStarted ) 1242 { 1243 SAXException except; 1244 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "characters method called before startDocument" ) ); 1245 throw except; 1246 } 1247 1248 sal_Bool bThrowException(sal_False); 1249 if( aChars.getLength() ) 1250 { 1251 if( m_bIsCDATA ) 1252 bThrowException = !mp_SaxWriterHelper->writeString( aChars, sal_False, sal_False ); 1253 else 1254 { 1255 // Note : nFirstLineBreakOccurence is not exact, because we don't know, how 1256 // many 2 and 3 byte chars are inbetween. However this whole stuff 1257 // is eitherway for pretty printing only, so it does not need to be exact. 1258 sal_Int32 nLength(0); 1259 sal_Int32 nIndentPrefix(-1); 1260 if (m_bAllowLineBreak) 1261 { 1262 sal_Int32 nFirstLineBreakOccurence = getFirstLineBreak( aChars ); 1263 1264 nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(), 1265 ! m_bIsCDATA , sal_False ); 1266 nIndentPrefix = getIndentPrefixLength( 1267 nFirstLineBreakOccurence >= 0 ? nFirstLineBreakOccurence : nLength ); 1268 } 1269 else 1270 nIndentPrefix = getIndentPrefixLength(nLength); 1271 1272 // insert indentation 1273 if( nIndentPrefix >= 0 ) 1274 { 1275 if( isFirstCharWhitespace( aChars.getStr() ) ) 1276 mp_SaxWriterHelper->insertIndentation( nIndentPrefix - 1 ); 1277 else 1278 mp_SaxWriterHelper->insertIndentation( nIndentPrefix ); 1279 } 1280 bThrowException = !mp_SaxWriterHelper->writeString(aChars, sal_True , sal_False); 1281 } 1282 } 1283 if (bThrowException) 1284 { 1285 SAXInvalidCharacterException except; 1286 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1287 throw except; 1288 } 1289 } 1290 1291 1292 void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException) 1293 { 1294 if( ! m_bDocStarted ) 1295 { 1296 throw SAXException (); 1297 } 1298 1299 m_bForceLineBreak = sal_True; 1300 } 1301 1302 void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData) 1303 throw (SAXException, RuntimeException) 1304 { 1305 if( ! m_bDocStarted || m_bIsCDATA ) 1306 { 1307 throw SAXException(); 1308 } 1309 1310 sal_Int32 nLength(0); 1311 if (m_bAllowLineBreak) 1312 { 1313 nLength = 2; // "<?" 1314 nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), sal_False, sal_False ); 1315 1316 nLength += 1; // " " 1317 1318 nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), sal_False, sal_False ); 1319 1320 nLength += 2; // "?>" 1321 } 1322 1323 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1324 1325 if( nPrefix >= 0 ) 1326 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1327 1328 if (!mp_SaxWriterHelper->processingInstruction(aTarget, aData)) 1329 { 1330 SAXException except; 1331 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1332 throw except; 1333 } 1334 } 1335 1336 1337 void SAXWriter::setDocumentLocator(const Reference< XLocator >&) 1338 throw (SAXException, RuntimeException) 1339 { 1340 1341 } 1342 1343 void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException) 1344 { 1345 if( ! m_bDocStarted || m_bIsCDATA) 1346 { 1347 throw SAXException (); 1348 } 1349 1350 sal_Int32 nLength = 9; 1351 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1352 if( nPrefix >= 0 ) 1353 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1354 1355 mp_SaxWriterHelper->startCDATA(); 1356 1357 m_bIsCDATA = sal_True; 1358 } 1359 1360 void SAXWriter::endCDATA(void) throw (RuntimeException) 1361 { 1362 if( ! m_bDocStarted | ! m_bIsCDATA) 1363 { 1364 SAXException except; 1365 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "endCDATA was called without startCDATA" ) ); 1366 throw except; 1367 } 1368 1369 sal_Int32 nLength = 3; 1370 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1371 if( nPrefix >= 0 ) 1372 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1373 1374 mp_SaxWriterHelper->endCDATA(); 1375 1376 m_bIsCDATA = sal_False; 1377 } 1378 1379 1380 void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException) 1381 { 1382 if( ! m_bDocStarted || m_bIsCDATA ) 1383 { 1384 throw SAXException(); 1385 } 1386 1387 sal_Int32 nLength(0); 1388 if (m_bAllowLineBreak) 1389 { 1390 nLength = 4; // "<!--" 1391 nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), sal_False, sal_False); 1392 1393 nLength += 3; 1394 } 1395 1396 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1397 if( nPrefix >= 0 ) 1398 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1399 1400 if (!mp_SaxWriterHelper->comment(sComment)) 1401 { 1402 SAXException except; 1403 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1404 throw except; 1405 } 1406 } 1407 1408 1409 void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException) 1410 { 1411 if( ! m_bDocStarted || m_bAllowLineBreak ) { 1412 throw SAXException(); 1413 } 1414 1415 m_bAllowLineBreak = sal_True; 1416 } 1417 1418 void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException) 1419 { 1420 1421 if( ! m_bDocStarted ) 1422 { 1423 throw SAXException (); 1424 } 1425 if( m_bIsCDATA ) 1426 { 1427 throw SAXException(); 1428 } 1429 1430 if( sString.matchAsciiL( "<?xml", 5 ) ) 1431 return; 1432 1433 sal_Int32 nLength(0); 1434 if (m_bAllowLineBreak) 1435 nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), sal_False, sal_False ); 1436 1437 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1438 if( nPrefix >= 0 ) 1439 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1440 1441 if (!mp_SaxWriterHelper->writeString( sString, sal_False, sal_False)) 1442 { 1443 SAXException except; 1444 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1445 throw except; 1446 } 1447 } 1448 1449 } 1450 1451