xref: /AOO41X/main/xmloff/source/core/nmspmap.cxx (revision 63bba73cc51e0afb45f8a8d578158724bb5afee8)
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