Welcome to mirror list, hosted at ThFree Co, Russian Federation.

AttributeAction.cs « XsltOld « Xsl « Xml « System « System.Data.SqlXml « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c26a03b4428fa7ae486f01d7d31dc09220578295 (plain)
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
146
147
148
//------------------------------------------------------------------------------
// <copyright file="AttributeAction.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------

namespace System.Xml.Xsl.XsltOld {
    using Res = System.Xml.Utils.Res;
    using System;
    using System.Diagnostics;
    using System.Xml;
    using System.Xml.XPath;

    internal class AttributeAction : ContainerAction {
        private const int NameDone          = 2;

        private Avt               nameAvt;
        private Avt               nsAvt;
        private InputScopeManager manager;
        // Compile time precalculated AVTs
        private string            name;
        private string            nsUri;
        private PrefixQName       qname; // When we not have AVTs at all we can do this. null otherwise.

        private static PrefixQName CreateAttributeQName(string name, string nsUri, InputScopeManager manager) {
            // if name == "xmlns" we don't need to generate this attribute.
            // to avoid i'ts generation we can return false and not add AtributeCation to it's parent container action
            // for now not creating this.qname will do the trick at execution time
            if (name  == "xmlns") return null;
            if (nsUri == XmlReservedNs.NsXmlNs) {
                throw XsltException.Create(Res.Xslt_ReservedNS, nsUri);
            }

            PrefixQName qname = new PrefixQName();
            qname.SetQName(name);

            qname.Namespace = nsUri != null ? nsUri : manager.ResolveXPathNamespace(qname.Prefix);

            if (qname.Prefix.StartsWith("xml", StringComparison.Ordinal)) {
                if (qname.Prefix.Length == 3) { // prefix == "xml"
                    if (qname.Namespace == XmlReservedNs.NsXml && (qname.Name == "lang" || qname.Name == "space")) {
                        // preserve prefix for xml:lang and xml:space
                    }
                    else {
                        qname.ClearPrefix();
                    }
                }
                else if (qname.Prefix == "xmlns") {
                    if (qname.Namespace == XmlReservedNs.NsXmlNs) {
                        // if NS wasn't specified we have to use prefix to find it and this is imposible for 'xmlns' 
                        throw XsltException.Create(Res.Xslt_InvalidPrefix, qname.Prefix);
                    }
                    else {
                        qname.ClearPrefix();
                    }
                }
            }
            return qname;
        }

        internal override void Compile(Compiler compiler) {
            CompileAttributes(compiler);
            CheckRequiredAttribute(compiler, this.nameAvt, "name");

            this.name  = PrecalculateAvt(ref this.nameAvt);
            this.nsUri = PrecalculateAvt(ref this.nsAvt  );

            // if both name and ns are not AVT we can calculate qname at compile time and will not need namespace manager anymore
            if (this.nameAvt == null && this.nsAvt == null) {
                if(this.name != "xmlns") {
                    this.qname = CreateAttributeQName(this.name, this.nsUri, compiler.CloneScopeManager());                    
                }
            }
            else {
                this.manager = compiler.CloneScopeManager();
            }

            if (compiler.Recurse()) {
                CompileTemplate(compiler);
                compiler.ToParent();
            }
        }

        internal override bool CompileAttribute(Compiler compiler) {
            string name   = compiler.Input.LocalName;
            string value  = compiler.Input.Value;
            if (Ref.Equal(name, compiler.Atoms.Name)) {
                this.nameAvt = Avt.CompileAvt(compiler, value);
            }
            else if (Ref.Equal(name, compiler.Atoms.Namespace)) {
                this.nsAvt = Avt.CompileAvt(compiler, value);
            }
            else {
                return false;
            }

            return true;
        }

        internal override void Execute(Processor processor, ActionFrame frame) {
            Debug.Assert(processor != null && frame != null);

            switch (frame.State) {
            case Initialized:
                if(this.qname != null) {
                    frame.CalulatedName = this.qname;
                }
                else {
                    frame.CalulatedName = CreateAttributeQName(
                        this.nameAvt == null ? this.name  : this.nameAvt.Evaluate(processor, frame),
                        this.nsAvt   == null ? this.nsUri : this.nsAvt  .Evaluate(processor, frame),
                        this.manager
                    );
                    if(frame.CalulatedName == null) {
                        // name == "xmlns" case. Ignore xsl:attribute
                        frame.Finished();
                        break;
                    }
                }
                goto case NameDone;
            case NameDone :
                {
                    PrefixQName qname = frame.CalulatedName;
                    if (processor.BeginEvent(XPathNodeType.Attribute, qname.Prefix, qname.Name, qname.Namespace, false) == false) {
                        // Come back later
                        frame.State = NameDone;
                        break;
                    }

                    processor.PushActionFrame(frame);
                    frame.State = ProcessingChildren;
                    break;                              // Allow children to run
                }
            case ProcessingChildren:
                if (processor.EndEvent(XPathNodeType.Attribute) == false) {
                    frame.State = ProcessingChildren;
                    break;
                }
                frame.Finished();
                break;
            default:
                Debug.Fail("Invalid ElementAction execution state");
    		    break;
            }
        }
    }
}