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 149
|
//------------------------------------------------------------------------------
// <copyright file="UnionExpr.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
namespace MS.Internal.Xml.XPath {
using System;
using System.Xml;
using System.Xml.XPath;
using System.Diagnostics;
using System.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;
this.advance1 = true;
this.advance2 = true;
}
private UnionExpr(UnionExpr other) : base(other) {
this.qy1 = Clone(other.qy1);
this.qy2 = Clone(other.qy2);
this.advance1 = other.advance1;
this.advance2 = other.advance2;
this.currentNode = Clone(other.currentNode);
this.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();
}
}
}
|