| File: FrameworkFork\Microsoft.Xml\Xml\XPath\Internal\UnionExpr.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. namespace MS.Internal.Xml.XPath { using System; using Microsoft.Xml; using Microsoft.Xml.XPath; using System.Diagnostics; using Microsoft.Xml.Xsl; internal sealed class UnionExpr : Query { internal Query qy1, qy2; private bool _advance1,_advance2; private XPathNavigator _currentNode; private XPathNavigator _nextNode; public UnionExpr(Query query1, Query query2) { this.qy1 = query1; this.qy2 = query2; _advance1 = true; _advance2 = true; } private UnionExpr(UnionExpr other) : base(other) { this.qy1 = Clone(other.qy1); this.qy2 = Clone(other.qy2); _advance1 = other._advance1; _advance2 = other._advance2; _currentNode = Clone(other._currentNode); _nextNode = Clone(other._nextNode); } public override void Reset() { qy1.Reset(); qy2.Reset(); _advance1 = true; _advance2 = true; _nextNode = null; } public override void SetXsltContext(XsltContext xsltContext) { qy1.SetXsltContext(xsltContext); qy2.SetXsltContext(xsltContext); } public override object Evaluate(XPathNodeIterator context) { qy1.Evaluate(context); qy2.Evaluate(context); _advance1 = true; _advance2 = true; _nextNode = null; base.ResetCount(); return this; } private XPathNavigator ProcessSamePosition(XPathNavigator result) { _currentNode = result; _advance1 = _advance2 = true; return result; } private XPathNavigator ProcessBeforePosition(XPathNavigator res1, XPathNavigator res2) { _nextNode = res2; _advance2 = false; _advance1 = true; _currentNode = res1; return res1; } private XPathNavigator ProcessAfterPosition(XPathNavigator res1, XPathNavigator res2) { _nextNode = res1; _advance1 = false; _advance2 = true; _currentNode = res2; return res2; } public override XPathNavigator Advance() { XPathNavigator res1, res2; XmlNodeOrder order = 0; if (_advance1) { res1 = qy1.Advance(); } else { res1 = _nextNode; } if (_advance2) { res2 = qy2.Advance(); } else { res2 = _nextNode; } if (res1 != null && res2 != null) { order = CompareNodes(res1, res2); } else if (res2 == null) { _advance1 = true; _advance2 = false; _currentNode = res1; _nextNode = null; return res1; } else { _advance1 = false; _advance2 = true; _currentNode = res2; _nextNode = null; return res2; } if (order == XmlNodeOrder.Before) { return ProcessBeforePosition(res1, res2); } else if (order == XmlNodeOrder.After) { return ProcessAfterPosition(res1, res2); } else { // BugBug. In case of Unknown we sorting as the same. return ProcessSamePosition(res1); } } public override XPathNavigator MatchNode(XPathNavigator xsltContext) { if (xsltContext != null) { XPathNavigator result = qy1.MatchNode(xsltContext); if (result != null) { return result; } return qy2.MatchNode(xsltContext); } return null; } public override XPathResultType StaticType { get { return XPathResultType.NodeSet; } } public override XPathNodeIterator Clone() { return new UnionExpr(this); } public override XPathNavigator Current { get { return _currentNode; } } public override int CurrentPosition { get { throw new InvalidOperationException(); } } public override void PrintQuery(XmlWriter w) { w.WriteStartElement(this.GetType().Name); if (qy1 != null) { qy1.PrintQuery(w); } if (qy2 != null) { qy2.PrintQuery(w); } w.WriteEndElement(); } } }