xref: /aoo41x/main/xmloff/source/core/nmspmap.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include <tools/debug.hxx>
31 #include <rtl/ustring.hxx>
32 #include <rtl/ustrbuf.hxx>
33 
34 #ifndef _XMLTOKEN_HXX
35 #include <xmloff/xmltoken.hxx>
36 #endif
37 #include <xmloff/nmspmap.hxx>
38 
39 #include "xmloff/xmlnmspe.hxx"
40 
41 
42 using ::rtl::OUString;
43 using ::rtl::OUStringBuffer;
44 using namespace ::xmloff::token;
45 
46 /* The basic idea of this class is that we have two two ways to search our
47  * data...by prefix and by key. We use an STL hash_map for fast prefix
48  * searching and an STL map for fast key searching.
49  *
50  * The references to an 'Index' refer to an earlier implementation of the
51  * name space map and remain to support code which uses these interfaces.
52  *
53  * In this implementation, key and index should always be the same number.
54  *
55  * All references to Indices are now deprecated and the corresponding
56  * 'Key' methods should be used instead
57  *
58  * Martin 13/06/01
59  */
60 
61 SvXMLNamespaceMap::SvXMLNamespaceMap()
62 : sXMLNS( GetXMLToken ( XML_XMLNS ) )
63 {
64 }
65 
66 SvXMLNamespaceMap::SvXMLNamespaceMap( const SvXMLNamespaceMap& rMap )
67 : sXMLNS( GetXMLToken ( XML_XMLNS ) )
68 {
69 	aNameHash = rMap.aNameHash;
70 	aNameMap  = rMap.aNameMap;
71 }
72 
73 void SvXMLNamespaceMap::operator=( const SvXMLNamespaceMap& rMap )
74 {
75     aNameHash = rMap.aNameHash;
76     aNameMap = rMap.aNameMap;
77 }
78 
79 SvXMLNamespaceMap::~SvXMLNamespaceMap()
80 {
81 	QNameCache::iterator aIter = aQNameCache.begin(), aEnd = aQNameCache.end();
82 	while ( aIter != aEnd )
83 	{
84 		const OUString *pString = (*aIter).first.second;
85 		aIter++;
86 		delete pString;
87     }
88 }
89 
90 int SvXMLNamespaceMap::operator ==( const SvXMLNamespaceMap& rCmp ) const
91 {
92 	return static_cast < int > (aNameHash == rCmp.aNameHash);
93 }
94 
95 sal_uInt16 SvXMLNamespaceMap::_Add( const OUString& rPrefix, const OUString &rName, sal_uInt16 nKey )
96 {
97 	if( XML_NAMESPACE_UNKNOWN == nKey )
98 	{
99 		// create a new unique key with UNKNOWN flag set
100 		nKey = XML_NAMESPACE_UNKNOWN_FLAG;
101 		do
102 		{
103 			NameSpaceMap::const_iterator aIter = aNameMap.find ( nKey );
104 			if( aIter == aNameMap.end() )
105 				break;
106 			nKey++;
107 		}
108 		while ( sal_True );
109 	}
110     ::vos::ORef<NameSpaceEntry> pEntry(new NameSpaceEntry);
111 	pEntry->sName   = rName;
112 	pEntry->nKey    = nKey;
113 	pEntry->sPrefix = rPrefix;
114 	aNameHash[ rPrefix ] = pEntry;
115 	aNameMap [ nKey ]	 = pEntry;
116 	return nKey;
117 }
118 
119 sal_uInt16 SvXMLNamespaceMap::Add( const OUString& rPrefix, const OUString& rName,
120 							   sal_uInt16 nKey )
121 {
122 	if( XML_NAMESPACE_UNKNOWN == nKey )
123 		nKey = GetKeyByName( rName );
124 
125 	DBG_ASSERT( XML_NAMESPACE_NONE != nKey,
126 				"SvXMLNamespaceMap::Add: invalid namespace key" );
127 
128 	if( XML_NAMESPACE_NONE == nKey )
129 		return USHRT_MAX;
130 
131 	if ( aNameHash.find ( rPrefix ) == aNameHash.end() )
132 		nKey = _Add( rPrefix, rName, nKey );
133 
134 	return nKey;
135 }
136 
137 sal_uInt16 SvXMLNamespaceMap::AddIfKnown( const OUString& rPrefix, const OUString& rName )
138 {
139 	sal_uInt16 nKey = GetKeyByName( rName );
140 
141 	DBG_ASSERT( XML_NAMESPACE_NONE != nKey,
142 				"SvXMLNamespaceMap::AddIfKnown: invalid namespace key" );
143 
144 	if( XML_NAMESPACE_NONE == nKey )
145 		return XML_NAMESPACE_UNKNOWN;
146 
147 	if( XML_NAMESPACE_UNKNOWN != nKey )
148     {
149         NameSpaceHash::const_iterator aIter = aNameHash.find( rPrefix );
150         if( aIter == aNameHash.end() || (*aIter).second->sName != rName )
151             nKey = _Add( rPrefix, rName, nKey );
152     }
153 
154 	return nKey;
155 }
156 
157 
158 sal_uInt16 SvXMLNamespaceMap::GetKeyByPrefix( const OUString& rPrefix ) const
159 {
160 	NameSpaceHash::const_iterator aIter = aNameHash.find(rPrefix);
161 	return (aIter != aNameHash.end()) ? (*aIter).second->nKey : USHRT_MAX;
162 }
163 
164 sal_uInt16 SvXMLNamespaceMap::GetKeyByName( const OUString& rName ) const
165 {
166 	sal_uInt16 nKey = XML_NAMESPACE_UNKNOWN;
167 	NameSpaceHash::const_iterator aIter = aNameHash.begin(), aEnd = aNameHash.end();
168 	while (aIter != aEnd )
169 	{
170 		if ((*aIter).second->sName == rName)
171 		{
172 			nKey = (*aIter).second->nKey;
173 			break;
174 		}
175 		aIter++;
176 	}
177 	return nKey;
178 }
179 
180 const OUString& SvXMLNamespaceMap::GetPrefixByKey( sal_uInt16 nKey ) const
181 {
182 	NameSpaceMap::const_iterator aIter = aNameMap.find (nKey);
183 	return (aIter != aNameMap.end()) ? (*aIter).second->sPrefix : sEmpty;
184 }
185 
186 const OUString& SvXMLNamespaceMap::GetNameByKey( sal_uInt16 nKey ) const
187 {
188 	NameSpaceMap::const_iterator aIter = aNameMap.find (nKey);
189 	return (aIter != aNameMap.end()) ? (*aIter).second->sName : sEmpty;
190 }
191 
192 OUString SvXMLNamespaceMap::GetAttrNameByKey( sal_uInt16 nKey ) const
193 {
194 	OUStringBuffer sAttrName;
195 	NameSpaceMap::const_iterator aIter = aNameMap.find ( nKey );
196 	if (aIter != aNameMap.end())
197 	{
198 		sAttrName.append( sXMLNS  );
199         const ::rtl::OUString & prefix( (*aIter).second->sPrefix );
200         if (prefix.getLength()) // not default namespace
201         {
202             sAttrName.append( sal_Unicode(':') );
203             sAttrName.append( prefix );
204         }
205 	}
206 	return sAttrName.makeStringAndClear();
207 }
208 
209 OUString SvXMLNamespaceMap::GetQNameByKey( sal_uInt16 nKey,
210 							const OUString& rLocalName,
211                             sal_Bool bCache) const
212 {
213 	// We always want to return at least the rLocalName...
214 
215 	switch ( nKey )
216 	{
217 		case XML_NAMESPACE_UNKNOWN:
218 			// ...if it's a completely unknown namespace, assert and return the local name
219 			DBG_ASSERT( sal_False, "SvXMLNamespaceMap::GetQNameByKey: invalid namespace key" );
220 		case XML_NAMESPACE_NONE:
221 			// ...if there isn't one, return the local name
222 			return rLocalName;
223 		case XML_NAMESPACE_XMLNS:
224 		{
225 			// ...if it's in the xmlns namespace, make the prefix
226 			// don't bother caching this, it rarely happens
227 			OUStringBuffer sQName;
228 			sQName.append ( sXMLNS );
229             if (rLocalName.getLength()) // not default namespace
230             {
231                 sQName.append ( sal_Unicode(':') );
232                 sQName.append ( rLocalName );
233             }
234 			return sQName.makeStringAndClear();;
235 		}
236 		case XML_NAMESPACE_XML:
237 		{
238             // this namespace is reserved, and needs not to be declared
239 			OUStringBuffer sQName;
240 			sQName.append ( GetXMLToken(XML_XML) );
241 			sQName.append ( sal_Unicode(':') );
242 			sQName.append ( rLocalName );
243 			return sQName.makeStringAndClear();;
244 		}
245 		default:
246 		{
247             QNameCache::const_iterator aQCacheIter;
248             if (bCache)
249 			    aQCacheIter = aQNameCache.find ( QNamePair ( nKey, &rLocalName ) );
250             else
251                 aQCacheIter = aQNameCache.end();
252 			if ( aQCacheIter != aQNameCache.end() )
253 				return (*aQCacheIter).second;
254 			else
255 			{
256 				NameSpaceMap::const_iterator aIter = aNameMap.find ( nKey );
257 				if ( aIter != aNameMap.end() )
258 				{
259 					OUStringBuffer sQName;
260 					// ...if it's in our map, make the prefix
261                     const OUString & prefix( (*aIter).second->sPrefix );
262                     if (prefix.getLength()) // not default namespace
263                     {
264                         sQName.append( prefix );
265                         sQName.append( sal_Unicode(':') );
266                     }
267                     sQName.append ( rLocalName );
268                     if (bCache)
269                     {
270                         OUString sString(sQName.makeStringAndClear());
271                         OUString *pString = new OUString ( rLocalName );
272                         const_cast < QNameCache * > (&aQNameCache)->operator[] ( QNamePair ( nKey, pString ) ) = sString;
273                         return sString;
274                     }
275                     else
276                         return sQName.makeStringAndClear();
277 				}
278 				else
279 				{
280 					// ... if it isn't, this is a Bad Thing, assert and return the local name
281 					DBG_ASSERT( sal_False, "SvXMLNamespaceMap::GetQNameByKey: invalid namespace key" );
282 					return rLocalName;
283 				}
284 			}
285 		}
286 	}
287 }
288 
289 sal_uInt16 SvXMLNamespaceMap::_GetKeyByAttrName(
290 							const OUString& rAttrName,
291 							OUString *pLocalName,
292                             sal_Bool bCache) const
293 {
294 	return _GetKeyByAttrName( rAttrName, 0, pLocalName, 0, bCache );
295 }
296 
297 sal_uInt16 SvXMLNamespaceMap::_GetKeyByAttrName( const OUString& rAttrName,
298 											OUString *pPrefix,
299 											OUString *pLocalName,
300 											OUString *pNamespace,
301                                             sal_Bool bCache) const
302 {
303 	sal_uInt16 nKey = XML_NAMESPACE_UNKNOWN;
304 
305     NameSpaceHash::const_iterator it;
306     if (bCache)
307         it = aNameCache.find ( rAttrName );
308     else
309         it = aNameCache.end();
310     if ( it != aNameCache.end() )
311 	{
312         const NameSpaceEntry &rEntry = (*it).second.getBody();
313         if ( pPrefix )
314             *pPrefix = rEntry.sPrefix;
315         if ( pLocalName )
316             *pLocalName = rEntry.sName;
317         nKey = rEntry.nKey;
318         if ( pNamespace )
319 		{
320             NameSpaceMap::const_iterator aMapIter = aNameMap.find (nKey);
321             *pNamespace = aMapIter != aNameMap.end() ? (*aMapIter).second->sName : sEmpty;
322         }
323     }
324     else
325     {
326 	vos::ORef<NameSpaceEntry> xEntry(new NameSpaceEntry());
327 
328         sal_Int32 nColonPos = rAttrName.indexOf( sal_Unicode(':') );
329         if( -1L == nColonPos )
330         {
331             // case: no ':' found -> default namespace
332             xEntry->sPrefix = OUString();
333             xEntry->sName = rAttrName;
334         }
335         else
336         {
337             // normal case: ':' found -> get prefix/suffix
338             xEntry->sPrefix = rAttrName.copy( 0L, nColonPos );
339             xEntry->sName = rAttrName.copy( nColonPos + 1L );
340         }
341 
342         if( pPrefix )
343             *pPrefix = xEntry->sPrefix;
344         if( pLocalName )
345             *pLocalName = xEntry->sName;
346 
347         NameSpaceHash::const_iterator aIter = aNameHash.find( xEntry->sPrefix );
348         if ( aIter != aNameHash.end() )
349 		{
350             // found: retrieve namespace key
351             nKey = xEntry->nKey = (*aIter).second->nKey;
352             if ( pNamespace )
353                 *pNamespace = (*aIter).second->sName;
354         }
355         else if ( xEntry->sPrefix == sXMLNS )
356             // not found, but xmlns prefix: return xmlns 'namespace'
357             nKey = xEntry->nKey = XML_NAMESPACE_XMLNS;
358         else if( nColonPos == -1L )
359             // not found, and no namespace: 'namespace' none
360             nKey = xEntry->nKey = XML_NAMESPACE_NONE;
361 
362         if (bCache)
363 	{
364 	    typedef std::pair< const rtl::OUString, vos::ORef<NameSpaceEntry> > value_type;
365 	    (void) const_cast<NameSpaceHash*>(&aNameCache)->insert (value_type (rAttrName, xEntry));
366 	}
367     }
368 
369 	return nKey;
370 }
371 
372 sal_uInt16 SvXMLNamespaceMap::GetFirstKey() const
373 {
374 	return aNameMap.empty() ? USHRT_MAX : (*aNameMap.begin()).second->nKey;
375 }
376 
377 sal_uInt16 SvXMLNamespaceMap::GetNextKey( sal_uInt16 nLastKey ) const
378 {
379 	NameSpaceMap::const_iterator aIter = aNameMap.find ( nLastKey );
380 	return (++aIter == aNameMap.end()) ? USHRT_MAX : (*aIter).second->nKey;
381 }
382 
383 
384 // All methods after this are deprecated...
385 
386 sal_uInt16 SvXMLNamespaceMap::GetKeyByIndex( sal_uInt16 nIdx ) const
387 {
388 	return nIdx;
389 }
390 
391 sal_uInt16 SvXMLNamespaceMap::GetIndexByKey( sal_uInt16 nKey ) const
392 {
393 	return nKey;
394 }
395 sal_uInt16 SvXMLNamespaceMap::GetFirstIndex() const
396 {
397 	return aNameMap.empty() ? USHRT_MAX : (*aNameMap.begin()).second->nKey;
398 }
399 
400 sal_uInt16 SvXMLNamespaceMap::GetNextIndex( sal_uInt16 nOldIdx ) const
401 {
402 	NameSpaceMap::const_iterator aIter = aNameMap.find ( nOldIdx );
403 	return (++aIter == aNameMap.end()) ? USHRT_MAX : (*aIter).second->nKey;
404 }
405 
406 sal_Bool SvXMLNamespaceMap::AddAtIndex( sal_uInt16 /*nIdx*/, const OUString& rPrefix,
407 									const OUString& rName, sal_uInt16 nKey )
408 {
409 	sal_Bool bRet = sal_False;
410 
411 	if( XML_NAMESPACE_UNKNOWN == nKey )
412 		nKey = GetKeyByName( rName );
413 
414 	DBG_ASSERT( XML_NAMESPACE_NONE != nKey,
415 				"SvXMLNamespaceMap::AddAtIndex: invalid namespace key" );
416 	if( XML_NAMESPACE_NONE != nKey && ! ( aNameHash.count ( rPrefix ) ) )
417 	{
418 		_Add( rPrefix, rName, nKey );
419 		bRet = sal_True;
420 	}
421 	return bRet;
422 }
423 
424 sal_Bool SvXMLNamespaceMap::AddAtIndex( sal_uInt16 nIdx, const sal_Char *pPrefix,
425 					 				const sal_Char *pName, sal_uInt16 nKey )
426 {
427 	OUString sPrefix( OUString::createFromAscii(pPrefix) );
428 	OUString sName( OUString::createFromAscii(pName) );
429 
430 	return AddAtIndex( nIdx, sPrefix, sName, nKey );
431 }
432 
433 OUString SvXMLNamespaceMap::GetAttrNameByIndex( sal_uInt16 nIdx ) const
434 {
435 	return GetAttrNameByKey( nIdx );
436 }
437 
438 OUString SvXMLNamespaceMap::GetQNameByIndex( sal_uInt16 nIdx,
439 										   const OUString& rLocalName ) const
440 {
441 	return GetQNameByKey( nIdx, rLocalName );
442 }
443 
444 const OUString& SvXMLNamespaceMap::GetPrefixByIndex( sal_uInt16 nIdx ) const
445 {
446 	NameSpaceMap::const_iterator aIter = aNameMap.find (nIdx);
447 	return (aIter != aNameMap.end()) ? (*aIter).second->sPrefix : sEmpty;
448 }
449 
450 const OUString& SvXMLNamespaceMap::GetNameByIndex( sal_uInt16 nIdx ) const
451 {
452 	NameSpaceMap::const_iterator aIter = aNameMap.find (nIdx);
453 	return (aIter != aNameMap.end()) ? (*aIter).second->sName : sEmpty;
454 }
455 
456 sal_uInt16 SvXMLNamespaceMap::GetIndexByPrefix( const OUString& rPrefix ) const
457 {
458 	NameSpaceHash::const_iterator aIter = aNameHash.find(rPrefix);
459 	return (aIter != aNameHash.end()) ? (*aIter).second->nKey : USHRT_MAX;
460 }
461 sal_uInt16 SvXMLNamespaceMap::GetKeyByAttrName(
462 							const OUString& rAttrName,
463 							OUString *pLocalName,
464 							sal_uInt16 /*nIdxGuess*/) const
465 {
466 	return _GetKeyByAttrName( rAttrName, 0, pLocalName, 0 );
467 }
468 
469 sal_uInt16 SvXMLNamespaceMap::GetKeyByAttrName( const OUString& rAttrName,
470 											OUString *pPrefix,
471 											OUString *pLocalName,
472 											OUString *pNamespace,
473 											sal_uInt16 /*nIdxGuess*/ ) const
474 {
475 	return _GetKeyByAttrName ( rAttrName, pPrefix, pLocalName, pNamespace );
476 }
477 
478 sal_Bool SvXMLNamespaceMap::NormalizeURI( ::rtl::OUString& rName )
479 {
480     // try OASIS + W3 URI normalization
481     sal_Bool bSuccess = NormalizeOasisURN( rName );
482     if( ! bSuccess )
483         bSuccess = NormalizeW3URI( rName );
484     return bSuccess;
485 }
486 
487 sal_Bool SvXMLNamespaceMap::NormalizeW3URI( ::rtl::OUString& rName )
488 {
489     // check if URI matches:
490     // http://www.w3.org/[0-9]*/[:letter:]*
491     //                   (year)/(WG name)
492     // For the following WG/standards names:
493     // - xforms
494 
495     sal_Bool bSuccess = sal_False;
496 	const OUString sURIPrefix = GetXMLToken( XML_URI_W3_PREFIX );
497     if( rName.compareTo( sURIPrefix, sURIPrefix.getLength() ) == 0 )
498     {
499         const OUString sURISuffix = GetXMLToken( XML_URI_XFORMS_SUFFIX );
500         sal_Int32 nCompareFrom = rName.getLength() - sURISuffix.getLength();
501         if( rName.copy( nCompareFrom ).equals( sURISuffix ) )
502         {
503             // found W3 prefix, and xforms suffix
504             rName = GetXMLToken( XML_N_XFORMS_1_0 );
505             bSuccess = sal_True;
506         }
507     }
508     return bSuccess;
509 }
510 
511 sal_Bool SvXMLNamespaceMap::NormalizeOasisURN( ::rtl::OUString& rName )
512 {
513 	// #i38644#
514 	// we exported the wrong namespace for smil, so we correct this here on load
515 	// for older documents
516 	if( IsXMLToken( rName, ::xmloff::token::XML_N_SVG ) )
517 	{
518 		rName = GetXMLToken( ::xmloff::token::XML_N_SVG_COMPAT );
519 		return sal_True;
520 	}
521 	else if( IsXMLToken( rName, ::xmloff::token::XML_N_FO ) )
522 	{
523 		rName = GetXMLToken( ::xmloff::token::XML_N_FO_COMPAT );
524 		return sal_True;
525 	}
526 	else if( IsXMLToken( rName, ::xmloff::token::XML_N_SMIL ) ||
527 		  	 IsXMLToken( rName, ::xmloff::token::XML_N_SMIL_OLD )  )
528 	{
529 		rName = GetXMLToken( ::xmloff::token::XML_N_SMIL_COMPAT );
530 		return sal_True;
531 	}
532 
533 	//
534 	// Check if URN matches
535 	// :urn:oasis:names:tc:[^:]*:xmlns:[^:]*:1.[^:]*
536 	//                     |---|       |---| |-----|
537 	//                     TC-Id      Sub-Id Version
538 
539 	sal_Int32 nNameLen = rName.getLength();
540 	// :urn:oasis:names:tc.*
541 	const OUString& rOasisURN = GetXMLToken( XML_URN_OASIS_NAMES_TC );
542 	if( 0 != rName.compareTo( rOasisURN, rOasisURN.getLength() ) )
543 		return sal_False;
544 
545 	// :urn:oasis:names:tc:.*
546 	sal_Int32 nPos = rOasisURN.getLength();
547 	if( nPos >= nNameLen || rName[nPos] != ':' )
548 		return sal_False;
549 
550 	// :urn:oasis:names:tc:[^:]:.*
551 	sal_Int32 nTCIdStart = nPos+1;
552 	sal_Int32 nTCIdEnd = rName.indexOf( ':', nTCIdStart );
553 	if( -1 == nTCIdEnd )
554 		return sal_False;
555 
556 	// :urn:oasis:names:tc:[^:]:xmlns.*
557 	nPos = nTCIdEnd + 1;
558 	OUString sTmp( rName.copy( nPos ) );
559 	const OUString& rXMLNS = GetXMLToken( XML_XMLNS );
560 	if( 0!= sTmp.compareTo( rXMLNS, rXMLNS.getLength() ) )
561 		return sal_False;
562 
563 	// :urn:oasis:names:tc:[^:]:xmlns:.*
564 	nPos += rXMLNS.getLength();
565 	if( nPos >= nNameLen || rName[nPos] != ':' )
566 		return sal_False;
567 
568 	// :urn:oasis:names:tc:[^:]:xmlns:[^:]*:.*
569 	nPos = rName.indexOf( ':', nPos+1 );
570 	if( -1 == nPos )
571 		return sal_False;
572 
573 	// :urn:oasis:names:tc:[^:]:xmlns:[^:]*:[^:][^:][^:][^:]*
574 	sal_Int32 nVersionStart = nPos+1;
575 	if( nVersionStart+2 >= nNameLen ||
576 		-1 != rName.indexOf( ':', nVersionStart ) )
577 		return sal_False;
578 
579 	// :urn:oasis:names:tc:[^:]:xmlns:[^:]*:1\.[^:][^:]*
580 	if( rName[nVersionStart] != '1' || rName[nVersionStart+1] != '.' )
581 		return sal_False;
582 
583 	// replace [tcid] with current TCID and version with current version.
584 	OUStringBuffer aNewName( nNameLen +20 );
585 	aNewName.append( rName.copy( 0, nTCIdStart ) );
586 	aNewName.append( GetXMLToken( XML_OPENDOCUMENT ) );
587 	aNewName.append( rName.copy( nTCIdEnd, nVersionStart-nTCIdEnd ) );
588 	aNewName.append( GetXMLToken( XML_1_0 ) );
589 
590 	rName = aNewName.makeStringAndClear();
591 
592 	return sal_True;
593 }
594