1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Xml;
  8 
  9 namespace System.XPath
 10 {
 11     public enum NodeTestKind
 12     {
 13         piLiteralTestcommentNodeTesttextNodeTestpiNodeTestanyNodeTestprincipalNodeTestprefixTestnameTest
 14     }
 15 
 16     public string NodeTestStr(NodeTestKind kind)
 17     {
 18         switch (kind)
 19         {
 20             case NodeTestKind.piLiteralTest: return "pi-literal-test";
 21             case NodeTestKind.commentNodeTest: return "comment-node-test";
 22             case NodeTestKind.textNodeTest: return "text-node-test";
 23             case NodeTestKind.piNodeTest: return "pi-node-test";
 24             case NodeTestKind.anyNodeTest: return "any-node-test";
 25             case NodeTestKind.principalNodeTest: return "principal-node-test";
 26             case NodeTestKind.prefixTest: return "prefix-node-test";
 27             case NodeTestKind.nameTest: return "name-node-test";
 28         }
 29         return "<unknown node-test>";
 30     }
 31 
 32     public class NodeTest
 33     {
 34         public NodeTest(NodeTestKind kind_) : kind(kind_)
 35         {
 36         }
 37         public inline NodeTestKind Kind() const
 38         {
 39             return kind;
 40         }
 41         public virtual default ~NodeTest();
 42         public virtual bool Select(System.Xml.Node* nodeSystem.Xml.Axis axis) const
 43         {
 44             switch (kind)
 45             {
 46                 case NodeTestKind.commentNodeTest:
 47                 {
 48                     return node->IsCommentNode();
 49                 }
 50                 case NodeTestKind.textNodeTest:
 51                 {
 52                     return node->IsTextNode();
 53                 }
 54                 case NodeTestKind.piNodeTest:
 55                 {
 56                     return node->IsProcessingInstructionNode();
 57                 }
 58                 case NodeTestKind.anyNodeTest:
 59                 {
 60                     return true;
 61                 }
 62                 case NodeTestKind.principalNodeTest:
 63                 {
 64                     if (axis == System.Xml.Axis.attribute)
 65                     {
 66                         return node->IsAttributeNode();
 67                     }
 68                     else if (axis == System.Xml.Axis.ns)
 69                     {
 70                         #assert(false);
 71                     }
 72                     else
 73                     {
 74                         return node->IsElementNode();
 75                     }
 76                     break;
 77                 }
 78             }
 79             return false;
 80         }
 81         public virtual System.Xml.Element* ToXmlElement() const
 82         {
 83             System.Xml.Element* element = System.Xml.MakeElement("node-test");
 84             element->SetAttribute("kind"NodeTestStr(kind));
 85             return element;
 86         }
 87         private NodeTestKind kind;
 88     }
 89 
 90     public class PILiteralNodeTest : NodeTest
 91     {
 92         public explicit PILiteralNodeTest(Literal* literal_) : base(NodeTestKind.piLiteralTest)literal(literal_)
 93         {
 94         }
 95         public inline Literal* GetLiteral() const
 96         {
 97             return literal.Get();
 98         }
 99         public override bool Select(System.Xml.Node* nodeSystem.Xml.Axis axis) const
100         {
101             if (node->IsProcessingInstructionNode())
102             {
103                 System.Xml.ProcessingInstruction* pi = cast<System.Xml.ProcessingInstruction*>(node);
104                 if (pi->Target() == literal->Value())
105                 {
106                     return true;
107                 }
108             }
109             return false;
110         }
111         public override System.Xml.Element* ToXmlElement() const
112         {
113             System.Xml.Element* element = base->ToXmlElement();
114             element->AppendChild(literal->ToXmlElement());
115             return element;
116         }
117         private UniquePtr<Literal> literal;
118     }
119 
120     public class PrefixNodeTest : NodeTest
121     {
122         public PrefixNodeTest(const string& prefix_) : base(NodeTestKind.prefixTest)prefix(prefix_)
123         {
124         }
125         public override bool Select(System.Xml.Node* nodeSystem.Xml.Axis axis) const
126         {
127             if (axis == System.Xml.Axis.attribute)
128             {
129                 if (node->IsAttributeNode())
130                 {
131                     if (node->Prefix() == prefix)
132                     {
133                         return true;
134                     }
135                 }
136             }
137             else if (axis == System.Xml.Axis.ns)
138             {
139                 #assert(false);
140             }
141             else if (node->IsElementNode())
142             {
143                 if (node->Prefix() == prefix)
144                 {
145                     return true;
146                 }
147             }
148             return false;
149         }
150         public override System.Xml.Element* ToXmlElement() const
151         {
152             System.Xml.Element* element = base->ToXmlElement();
153             element->SetAttribute("prefix"prefix);
154             return element;
155         }
156         private string prefix;
157     }
158 
159     public class NameNodeTest : NodeTest
160     {
161         public NameNodeTest(const string& name_) : base(NodeTestKind.nameTest)name(name_)
162         {
163         }
164         public inline const string& Name() const
165         {
166             return name;
167         }
168         public override bool Select(System.Xml.Node* nodeSystem.Xml.Axis axis) const
169         {
170             if (axis == System.Xml.Axis.attribute)
171             {
172                 if (node->IsAttributeNode())
173                 {
174                     if (node->Name() == name)
175                     {
176                         return true;
177                     }
178                 }
179             }
180             else if (axis == System.Xml.Axis.ns)
181             {
182                 #assert(false);
183             }
184             else
185             {
186                 if (node->IsElementNode())
187                 {
188                     if (node->Name() == name)
189                     {
190                         return true;
191                     }
192                 }
193             }
194             return false;
195         }
196         public override System.Xml.Element* ToXmlElement() const
197         {
198             System.Xml.Element* element = base->ToXmlElement();
199             element->SetAttribute("name"name);
200             return element;
201         }
202         private string name;
203     }
204 
205     public class NodeSelectionOperation : System.Xml.NodeOperation
206     {
207         public NodeSelectionOperation(NodeTest* nodeTest_NodeSet& nodeSet_System.Xml.Axis axis_) : nodeTest(nodeTest_)nodeSet(nodeSet_)axis(axis_)
208         {
209         }
210         public override void Apply(System.Xml.Node* node)
211         {
212             if (nodeTest->Select(nodeaxis))
213             {
214                 nodeSet.Add(node);
215             }
216         }
217         private NodeTest* nodeTest;
218         private NodeSet& nodeSet;
219         private System.Xml.Axis axis;
220     }