| File: System\Xml\Xsl\Runtime\WhitespaceRuleReader.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; namespace System.Xml.Xsl.Runtime { /// <summary> /// </summary> internal sealed class WhitespaceRuleReader : XmlWrappingReader { private readonly WhitespaceRuleLookup _wsRules; private readonly BitStack _stkStrip; private bool _shouldStrip, _preserveAdjacent; private string? _val; public static XmlReader CreateReader(XmlReader baseReader, WhitespaceRuleLookup? wsRules) { if (wsRules == null) { return baseReader; // There is no rules to process } XmlReaderSettings? readerSettings = baseReader.Settings; if (readerSettings != null) { if (readerSettings.IgnoreWhitespace) { return baseReader; // V2 XmlReader that strips all WS } } else { XmlTextReader? txtReader = baseReader as XmlTextReader; if (txtReader != null && txtReader.WhitespaceHandling == WhitespaceHandling.None) { return baseReader; // V1 XmlTextReader that strips all WS } XmlTextReaderImpl? txtReaderImpl = baseReader as XmlTextReaderImpl; if (txtReaderImpl != null && txtReaderImpl.WhitespaceHandling == WhitespaceHandling.None) { return baseReader; // XmlTextReaderImpl that strips all WS } } return new WhitespaceRuleReader(baseReader, wsRules); } private WhitespaceRuleReader(XmlReader baseReader, WhitespaceRuleLookup wsRules) : base(baseReader) { Debug.Assert(wsRules != null); _val = null; _stkStrip = new BitStack(); _shouldStrip = false; _preserveAdjacent = false; _wsRules = wsRules; _wsRules.Atomize(baseReader.NameTable); } /// <summary> /// Override Value in order to possibly prepend extra whitespace. /// </summary> public override string Value { get { return _val ?? base.Value; } } /// <summary> /// Override Read in order to search for strippable whitespace, to concatenate adjacent text nodes, and to /// resolve entities. /// </summary> public override bool Read() { string? ws = null; // Clear text value _val = null; while (base.Read()) { switch (base.NodeType) { case XmlNodeType.Element: // Push boolean indicating whether whitespace children of this element should be stripped if (!base.IsEmptyElement) { _stkStrip.PushBit(_shouldStrip); // Strip if rules say we should and we're not within the scope of xml:space="preserve" _shouldStrip = _wsRules.ShouldStripSpace(base.LocalName, base.NamespaceURI) && (base.XmlSpace != XmlSpace.Preserve); } break; case XmlNodeType.EndElement: // Restore parent shouldStrip setting _shouldStrip = _stkStrip.PopBit(); break; case XmlNodeType.Text: case XmlNodeType.CDATA: // If preserving adjacent text, don't perform any further checks if (_preserveAdjacent) return true; if (_shouldStrip) { // Reader may report whitespace as Text or CDATA if (XmlCharType.IsOnlyWhitespace(base.Value)) goto case XmlNodeType.Whitespace; // If whitespace was cached, then prepend it to text or CDATA value if (ws != null) _val = string.Concat(ws, base.Value); // Preserve adjacent whitespace _preserveAdjacent = true; return true; } break; case XmlNodeType.Whitespace: case XmlNodeType.SignificantWhitespace: // If preserving adjacent text, don't perform any further checks if (_preserveAdjacent) return true; if (_shouldStrip) { // Save whitespace until it can be determined whether it will be stripped ws = ws == null ? base.Value : string.Concat(ws, base.Value); // Read next event continue; } break; case XmlNodeType.EndEntity: // Read next event continue; } // No longer preserve adjacent space _preserveAdjacent = false; return true; } return false; } } }