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