/// <summary>Re-initializes internal state to be ready for re-use.</summary> public void Reset() { // some declarations may be pending in nextScope nextScope.ClearMappings(); // store active scopes for re-use NamespaceScope scope = topScope; if (scope != null) { // need to reset active scopes before storing them for re-use scope.ClearMappings(); while (scope.parent != null) { scope = scope.parent; scope.ClearMappings(); } // attach free scopes to end of active scopes scope.parent = nextScope; // move the whole stack from topScope to nextScope nextScope = topScope; topScope = null; } // the 'xml' prefix is always declared nextScope.AddMapping("xml", Constants.XmlUri); }
/// <summary>Given a prefix mapping for a specific URI, this returns /// the prefix mapping previously in effect for the same URI.</summary> /// <remarks>This can be used to iterate backwards through the stack of /// prefix mappings for a given URI.</remarks> /// <param name="prefix"><see cref="ActiveMapping"/> instance for which /// we want to find the instance previously in effect with the same URI.</param> /// <returns><see cref="ActiveMapping"/> instance to look for, /// or <c>null</c> if none exists.</returns> public ActiveMapping PreviousUriMapping(ActiveMapping prefix) { string uri = prefix.Uri; // check active mapping record NamespaceMapping nsMapping = prefix.mappingsTop; if (nsMapping == null || !nsMapping.declared) { string msg = Resources.GetString(RsId.UndeclaredMapping); throw new XmlNamespacesException(String.Format(msg, prefix.Prefix)); } // find a parent scope where the same URI maps to an "active" prefix NamespaceScope scope = nsMapping.scope.parent; while (scope != null) { nsMapping = scope.FindByUri(uri); if (nsMapping != null) { ActiveMapping result = nsMapping.prefix; // result must be different from prefix, since the same prefix // cannot be "declared" with two different URIs at the same time if (result.IsDeclared) { Debug.Assert(result != prefix, Resources.GetString(RsId.InternalNsError)); return(result); } } scope = scope.parent; } return(null); }
/// <summary>Returns the most recently added namespace mapping "in effect" /// for a given URI.</summary> /// <remarks>"In effect" means that the prefix mapping must <b>not</b> have /// been "undeclared".</remarks> /// <param name="uri">Namespace URI to get mapping for.</param> /// <returns><see cref="ActiveMapping"/> instance for <c>uri</c>, or <c>null</c> /// if there is no such mapping.</returns> public ActiveMapping GetUriMapping(string uri) { NamespaceScope scope = topScope; while (scope != null) { NamespaceMapping nsMapping = scope.FindByUri(uri); if (nsMapping != null && nsMapping.declared) { return(nsMapping.prefix); } scope = scope.parent; } return(null); }
/// <param name="prefixStr">String containing prefix sub-string.</param> /// <param name="start">Start index of prefix sub-string.</param> /// <param name="len">Length of prefix sub-string.</param> public ActiveMapping GetPrefixMapping(string prefixStr, int start, int len) { NamespaceScope scope = topScope; while (scope != null) { NamespaceMapping nsMapping = scope.FindByPrefix(prefixStr, start, len); if (nsMapping != null) { return(nsMapping.prefix); } scope = scope.parent; } return(null); }
/// <summary>Establishes a new mapping for the prefix associated with this /// instance, to an URI in a namespace scope, and pushes it on the stack.</summary> /// <param name="scope">Namespace scope the new mapping will be part of.</param> /// <param name="uri">URI to be mapped to this instance's prefix.</param> /// <returns>Newly added <see cref="NamespaceMapping"/>.</returns> protected internal NamespaceMapping PushMapping(string uri, NamespaceScope scope) { NamespaceMapping result = namespaces.NewNSMapping(); result.prefix = this; result.scope = scope; result.declared = uri != null; if (result.declared) { result.uri = uri; } else { result.uri = this.Uri; } result.next = mappingsTop; mappingsTop = result; return(result); }
/// <summary>Deactivates namespace scope.</summary> /// <remarks>All namespace mappings that became active with this scope /// are going out of effect.</remarks> public void PopScope() { if (nextScope.emptyLevels > 0) { nextScope.emptyLevels--; } else if (topScope == null) // don't pop too many times { string msg = Resources.GetString(RsId.NoActiveNsScope); throw new InvalidOperationException(msg); } else { NamespaceScope oldNextScope = nextScope; // clear pending declarations oldNextScope.ClearMappings(); nextScope = topScope; topScope = topScope.parent; nextScope.parent = oldNextScope; nextScope.ClearMappings(); } }
/// <summary>Activates new namespace scope.</summary> /// <remarks>All namespace mappings that were added since the last /// call to <see cref="PushScope"/>are going into effect.</remarks> public void PushScope() { if (nextScope.nsMappings.Count == 0) { nextScope.emptyLevels++; } else { NamespaceScope newNextScope = nextScope.parent; nextScope.parent = topScope; topScope = nextScope; // assume it was reset if (newNextScope == null) { newNextScope = new NamespaceScope(this); } else { newNextScope.emptyLevels = 0; } nextScope = newNextScope; } }
/// <summary>Indicates if a namespace scope is the most recent scope.</summary> /// <param name="scope"><see cref="NamespaceScope"/> to be checked.</param> /// <returns><c>true</c> if <c>scope</c> is most recent, <c>false</c> otherwise.</returns> protected internal bool IsLastScope(NamespaceScope scope) { return scope == topScope || scope == nextScope; }
/// <summary>Activates new namespace scope.</summary> /// <remarks>All namespace mappings that were added since the last /// call to <see cref="PushScope"/>are going into effect.</remarks> public void PushScope() { if (nextScope.nsMappings.Count == 0) { nextScope.emptyLevels++; } else { NamespaceScope newNextScope = nextScope.parent; nextScope.parent = topScope; topScope = nextScope; // assume it was reset if (newNextScope == null) newNextScope = new NamespaceScope(this); else newNextScope.emptyLevels = 0; nextScope = newNextScope; } }
/// <summary>Deactivates namespace scope.</summary> /// <remarks>All namespace mappings that became active with this scope /// are going out of effect.</remarks> public void PopScope() { if (nextScope.emptyLevels > 0) nextScope.emptyLevels--; else if (topScope == null) { // don't pop too many times string msg = Resources.GetString(RsId.NoActiveNsScope); throw new InvalidOperationException(msg); } else { NamespaceScope oldNextScope = nextScope; // clear pending declarations oldNextScope.ClearMappings(); nextScope = topScope; topScope = topScope.parent; nextScope.parent = oldNextScope; nextScope.ClearMappings(); } }
/* Public Interface */ /// <summary>Initializes new instance.</summary> public XmlNamespaces() { nextScope = new NamespaceScope(this); // the 'xml' prefix is always declared nextScope.AddMapping("xml", Constants.XmlUri); }
/// <summary>Establishes a new mapping for the prefix associated with this /// instance, to an URI in a namespace scope, and pushes it on the stack.</summary> /// <param name="scope">Namespace scope the new mapping will be part of.</param> /// <param name="uri">URI to be mapped to this instance's prefix.</param> /// <returns>Newly added <see cref="NamespaceMapping"/>.</returns> protected internal NamespaceMapping PushMapping(string uri, NamespaceScope scope) { NamespaceMapping result = namespaces.NewNSMapping(); result.prefix = this; result.scope = scope; result.declared = uri != null; if (result.declared) result.uri = uri; else result.uri = this.Uri; result.next = mappingsTop; mappingsTop = result; return result; }
/// <summary>Indicates if a namespace scope is the most recent scope.</summary> /// <param name="scope"><see cref="NamespaceScope"/> to be checked.</param> /// <returns><c>true</c> if <c>scope</c> is most recent, <c>false</c> otherwise.</returns> protected internal bool IsLastScope(NamespaceScope scope) { return(scope == topScope || scope == nextScope); }