File: WhitespaceRuleReader.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (145 lines) | stat: -rw-r--r-- 5,822 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//------------------------------------------------------------------------------
// <copyright file="WhitespaceRuleReader.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Diagnostics;
using MS.Internal.Xml;

namespace System.Xml.Xsl.Runtime {

    /// <summary>
    /// </summary>
    internal class WhitespaceRuleReader : XmlWrappingReader {
        private WhitespaceRuleLookup wsRules;
        private BitStack stkStrip;
        private bool shouldStrip, preserveAdjacent;
        private string val;
        private XmlCharType xmlCharType = XmlCharType.Instance;

        static public 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);

            this.val = null;
            this.stkStrip = new BitStack();
            this.shouldStrip = false;
            this.preserveAdjacent = false;

            this.wsRules = wsRules;
            this.wsRules.Atomize(baseReader.NameTable);
        }

        /// <summary>
        /// Override Value in order to possibly prepend extra whitespace.
        /// </summary>
        public override string Value {
            get { return (this.val == null) ? base.Value : this.val; }
        }

        /// <summary>
        /// Override Read in order to search for strippable whitespace, to concatenate adjacent text nodes, and to
        /// resolve entities.
        /// </summary>
        public override bool Read() {
            XmlCharType xmlCharType = XmlCharType.Instance;
            string ws = null;

            // Clear text value
            this.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) {
                        this.stkStrip.PushBit(this.shouldStrip);

                        // Strip if rules say we should and we're not within the scope of xml:space="preserve"
                        this.shouldStrip = wsRules.ShouldStripSpace(base.LocalName, base.NamespaceURI) && (base.XmlSpace != XmlSpace.Preserve);
                    }
                    break;

                case XmlNodeType.EndElement:
                    // Restore parent shouldStrip setting
                    this.shouldStrip = this.stkStrip.PopBit();
                    break;

                case XmlNodeType.Text:
                case XmlNodeType.CDATA:
                    // If preserving adjacent text, don't perform any further checks
                    if (this.preserveAdjacent)
                        return true;

                    if (this.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)
                            this.val = string.Concat(ws, base.Value);

                        // Preserve adjacent whitespace
                        this.preserveAdjacent = true;
                        return true;
                    }
                    break;

                case XmlNodeType.Whitespace:
                case XmlNodeType.SignificantWhitespace:
                    // If preserving adjacent text, don't perform any further checks
                    if (this.preserveAdjacent)
                        return true;

                    if (this.shouldStrip) {
                        // Save whitespace until it can be determined whether it will be stripped
                        if (ws == null)
                            ws = base.Value;
                        else
                            ws = string.Concat(ws, base.Value);

                        // Read next event
                        continue;
                    }
                    break;
                case XmlNodeType.EndEntity:
                    // Read next event
                    continue;
                }

            // No longer preserve adjacent space
                this.preserveAdjacent = false;
                return true;
            }

            return false;
        }
    }
}