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