You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,35 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="AbsoluteQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
internal sealed class AbsoluteQuery : ContextQuery {
|
||||
public AbsoluteQuery() : base() {}
|
||||
private AbsoluteQuery(AbsoluteQuery other) : base(other) {}
|
||||
|
||||
public override object Evaluate(XPathNodeIterator context) {
|
||||
base.contextNode = context.Current.Clone();
|
||||
base.contextNode.MoveToRoot();
|
||||
count = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override XPathNavigator MatchNode(XPathNavigator context) {
|
||||
if (context != null && context.NodeType == XPathNodeType.Root) {
|
||||
return context;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new AbsoluteQuery(this); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="AstNode.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">sdub</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml.XPath;
|
||||
|
||||
internal abstract class AstNode {
|
||||
public enum AstType {
|
||||
Axis ,
|
||||
Operator ,
|
||||
Filter ,
|
||||
ConstantOperand ,
|
||||
Function ,
|
||||
Group ,
|
||||
Root ,
|
||||
Variable ,
|
||||
Error
|
||||
};
|
||||
|
||||
public abstract AstType Type { get; }
|
||||
public abstract XPathResultType ReturnType { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="AttributeQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
internal sealed class AttributeQuery : BaseAxisQuery {
|
||||
private bool onAttribute = false;
|
||||
|
||||
public AttributeQuery(Query qyParent, string Name, string Prefix, XPathNodeType Type) : base(qyParent, Name, Prefix, Type) {}
|
||||
private AttributeQuery(AttributeQuery other) : base(other) {
|
||||
this.onAttribute = other.onAttribute;
|
||||
}
|
||||
public override void Reset() {
|
||||
onAttribute = false;
|
||||
base.Reset();
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
while (true) {
|
||||
if (! onAttribute) {
|
||||
currentNode = qyInput.Advance();
|
||||
if (currentNode == null) {
|
||||
return null;
|
||||
}
|
||||
position = 0;
|
||||
currentNode = currentNode.Clone();
|
||||
onAttribute = currentNode.MoveToFirstAttribute();
|
||||
} else {
|
||||
onAttribute = currentNode.MoveToNextAttribute();
|
||||
}
|
||||
|
||||
if (onAttribute) {
|
||||
Debug.Assert(! currentNode.NamespaceURI.Equals(XmlReservedNs.NsXmlNs));
|
||||
if (matches(currentNode)) {
|
||||
position++;
|
||||
return currentNode;
|
||||
}
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
public override XPathNavigator MatchNode(XPathNavigator context) {
|
||||
if (context != null) {
|
||||
if (context.NodeType == XPathNodeType.Attribute && matches(context)) {
|
||||
XPathNavigator temp = context.Clone();
|
||||
if (temp.MoveToParent()) {
|
||||
return qyInput.MatchNode(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new AttributeQuery(this); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="Axis.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
internal class Axis : AstNode {
|
||||
private AxisType axisType;
|
||||
private AstNode input;
|
||||
private string prefix;
|
||||
private string name;
|
||||
private XPathNodeType nodeType;
|
||||
protected bool abbrAxis;
|
||||
|
||||
public enum AxisType {
|
||||
Ancestor,
|
||||
AncestorOrSelf,
|
||||
Attribute,
|
||||
Child,
|
||||
Descendant,
|
||||
DescendantOrSelf,
|
||||
Following,
|
||||
FollowingSibling,
|
||||
Namespace,
|
||||
Parent,
|
||||
Preceding,
|
||||
PrecedingSibling,
|
||||
Self,
|
||||
None
|
||||
};
|
||||
|
||||
// constructor
|
||||
public Axis(AxisType axisType, AstNode input, string prefix, string name, XPathNodeType nodetype) {
|
||||
Debug.Assert(prefix != null);
|
||||
Debug.Assert(name != null);
|
||||
this.axisType = axisType;
|
||||
this.input = input;
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
this.nodeType = nodetype;
|
||||
}
|
||||
|
||||
// constructor
|
||||
public Axis(AxisType axisType, AstNode input)
|
||||
: this(axisType, input, string.Empty, string.Empty, XPathNodeType.All)
|
||||
{
|
||||
this.abbrAxis = true;
|
||||
}
|
||||
|
||||
public override AstType Type { get {return AstType.Axis;} }
|
||||
|
||||
public override XPathResultType ReturnType { get {return XPathResultType.NodeSet;} }
|
||||
|
||||
public AstNode Input {
|
||||
get {return input;}
|
||||
set {input = value;}
|
||||
}
|
||||
|
||||
public string Prefix { get { return prefix; } }
|
||||
public string Name { get { return name; } }
|
||||
public XPathNodeType NodeType { get { return nodeType; } }
|
||||
public AxisType TypeOfAxis { get { return axisType; } }
|
||||
public bool AbbrAxis { get { return abbrAxis; } }
|
||||
|
||||
// Used by AstTree in Schema
|
||||
private string urn = string.Empty;
|
||||
public string Urn {
|
||||
get { return urn; }
|
||||
set { urn = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="baseaxisquery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Xml.Xsl;
|
||||
using System.Collections;
|
||||
|
||||
internal abstract class BaseAxisQuery : Query {
|
||||
internal Query qyInput;
|
||||
bool nameTest;
|
||||
string name;
|
||||
string prefix;
|
||||
string nsUri;
|
||||
XPathNodeType typeTest;
|
||||
|
||||
// these two things are the state of this class
|
||||
// that need to be reset whenever the context changes.
|
||||
protected XPathNavigator currentNode;
|
||||
protected int position;
|
||||
|
||||
protected BaseAxisQuery(Query qyInput) {
|
||||
this.name = string.Empty;
|
||||
this.prefix = string.Empty;
|
||||
this.nsUri = string.Empty;
|
||||
this.qyInput = qyInput;
|
||||
}
|
||||
protected BaseAxisQuery(Query qyInput, string name, string prefix, XPathNodeType typeTest) {
|
||||
Debug.Assert(qyInput != null);
|
||||
this.qyInput = qyInput;
|
||||
this.name = name;
|
||||
this.prefix = prefix;
|
||||
this.typeTest = typeTest;
|
||||
this.nameTest = prefix.Length != 0 || name.Length != 0;
|
||||
this.nsUri = string.Empty;
|
||||
}
|
||||
protected BaseAxisQuery(BaseAxisQuery other) : base(other) {
|
||||
this.qyInput = Clone(other.qyInput);
|
||||
this.name = other.name;
|
||||
this.prefix = other.prefix;
|
||||
this.nsUri = other.nsUri;
|
||||
this.typeTest = other.typeTest;
|
||||
this.nameTest = other.nameTest;
|
||||
this.position = other.position;
|
||||
this.currentNode = other.currentNode;
|
||||
}
|
||||
|
||||
public override void Reset() {
|
||||
position = 0;
|
||||
currentNode = null; // After this current will not point to context node from Evaluate() call
|
||||
// But this is ok, becuase there is no public Reset() on XPathNodeIterator
|
||||
qyInput.Reset();
|
||||
}
|
||||
|
||||
public override void SetXsltContext(XsltContext context) {
|
||||
Debug.Assert(context != null);
|
||||
nsUri = context.LookupNamespace(prefix);
|
||||
qyInput.SetXsltContext(context);
|
||||
}
|
||||
|
||||
protected string Name { get { return name; } }
|
||||
protected string Prefix { get { return prefix; } }
|
||||
protected string Namespace { get { return nsUri; } }
|
||||
protected bool NameTest { get { return nameTest; } }
|
||||
protected XPathNodeType TypeTest { get { return typeTest; } }
|
||||
|
||||
public override int CurrentPosition { get { return position; } }
|
||||
public override XPathNavigator Current { get { return currentNode; } }
|
||||
|
||||
public virtual bool matches(XPathNavigator e) {
|
||||
if (
|
||||
TypeTest == e.NodeType ||
|
||||
TypeTest == XPathNodeType.All ||
|
||||
TypeTest == XPathNodeType.Text && (e.NodeType == XPathNodeType.Whitespace || e.NodeType == XPathNodeType.SignificantWhitespace)
|
||||
) {
|
||||
if (NameTest) {
|
||||
if (name.Equals(e.LocalName) || name.Length == 0) {
|
||||
if (nsUri.Equals(e.NamespaceURI)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object Evaluate(XPathNodeIterator nodeIterator) {
|
||||
ResetCount();
|
||||
Reset();
|
||||
qyInput.Evaluate(nodeIterator);
|
||||
AssertQuery(qyInput);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override double XsltDefaultPriority { get {
|
||||
if (qyInput.GetType() != typeof(ContextQuery)) {
|
||||
return 0.5; // a/b a[b] id('s')/a
|
||||
}
|
||||
Debug.Assert(this is AttributeQuery || this is ChildrenQuery);
|
||||
if (name.Length != 0) {
|
||||
return 0; // p:foo, foo, processing-instruction("foo")
|
||||
}
|
||||
if (prefix.Length != 0) {
|
||||
return -0.25; // p:*
|
||||
}
|
||||
return -0.5; // *, text(), node()
|
||||
} }
|
||||
|
||||
public override XPathResultType StaticType { get { return XPathResultType.NodeSet; } }
|
||||
|
||||
public override void PrintQuery(XmlWriter w) {
|
||||
w.WriteStartElement(this.GetType().Name);
|
||||
if (NameTest) {
|
||||
w.WriteAttributeString("name", Prefix.Length != 0 ? Prefix + ':' + Name : Name);
|
||||
}
|
||||
if (TypeTest != XPathNodeType.Element) {
|
||||
w.WriteAttributeString("nodeType", TypeTest.ToString());
|
||||
}
|
||||
qyInput.PrintQuery(w);
|
||||
w.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="BooleanExpr.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Xml.Xsl;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
internal sealed class BooleanExpr : ValueQuery {
|
||||
private Query opnd1;
|
||||
private Query opnd2;
|
||||
private bool isOr;
|
||||
|
||||
public BooleanExpr(Operator.Op op, Query opnd1, Query opnd2) {
|
||||
Debug.Assert(op == Operator.Op.AND || op == Operator.Op.OR);
|
||||
Debug.Assert(opnd1 != null && opnd2 != null);
|
||||
if (opnd1.StaticType != XPathResultType.Boolean) {
|
||||
opnd1 = new BooleanFunctions(Function.FunctionType.FuncBoolean, opnd1);
|
||||
}
|
||||
if (opnd2.StaticType != XPathResultType.Boolean) {
|
||||
opnd2 = new BooleanFunctions(Function.FunctionType.FuncBoolean, opnd2);
|
||||
}
|
||||
this.opnd1 = opnd1;
|
||||
this.opnd2 = opnd2;
|
||||
isOr = (op == Operator.Op.OR);
|
||||
}
|
||||
private BooleanExpr(BooleanExpr other) : base(other) {
|
||||
this.opnd1 = Clone(other.opnd1);
|
||||
this.opnd2 = Clone(other.opnd2);
|
||||
this.isOr = other.isOr;
|
||||
}
|
||||
|
||||
public override void SetXsltContext(XsltContext context){
|
||||
opnd1.SetXsltContext(context);
|
||||
opnd2.SetXsltContext(context);
|
||||
}
|
||||
|
||||
public override object Evaluate(XPathNodeIterator nodeIterator) {
|
||||
object n1 = opnd1.Evaluate(nodeIterator);
|
||||
if (((bool) n1) == isOr) {
|
||||
return n1;
|
||||
}
|
||||
return opnd2.Evaluate(nodeIterator);
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new BooleanExpr(this); }
|
||||
public override XPathResultType StaticType { get { return XPathResultType.Boolean; } }
|
||||
|
||||
public override void PrintQuery(XmlWriter w) {
|
||||
w.WriteStartElement(this.GetType().Name);
|
||||
w.WriteAttributeString("op", (isOr ? Operator.Op.OR : Operator.Op.AND).ToString());
|
||||
opnd1.PrintQuery(w);
|
||||
opnd2.PrintQuery(w);
|
||||
w.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="BooleanFunctions.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Xml.Xsl;
|
||||
using FT = MS.Internal.Xml.XPath.Function.FunctionType;
|
||||
|
||||
internal sealed class BooleanFunctions : ValueQuery {
|
||||
Query arg;
|
||||
FT funcType;
|
||||
|
||||
public BooleanFunctions(FT funcType, Query arg) {
|
||||
this.arg = arg;
|
||||
this.funcType = funcType;
|
||||
}
|
||||
private BooleanFunctions(BooleanFunctions other) : base(other) {
|
||||
this.arg = Clone(other.arg);
|
||||
this.funcType = other.funcType;
|
||||
}
|
||||
|
||||
public override void SetXsltContext(XsltContext context) {
|
||||
if (arg != null) {
|
||||
arg.SetXsltContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
public override object Evaluate(XPathNodeIterator nodeIterator) {
|
||||
switch (funcType) {
|
||||
case FT.FuncBoolean : return toBoolean(nodeIterator);
|
||||
case FT.FuncNot : return Not(nodeIterator);
|
||||
case FT.FuncTrue : return true;
|
||||
case FT.FuncFalse : return false;
|
||||
case FT.FuncLang : return Lang(nodeIterator);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool toBoolean(double number) {
|
||||
return number != 0 && ! double.IsNaN(number);
|
||||
}
|
||||
internal static bool toBoolean(string str) {
|
||||
return str.Length > 0;
|
||||
}
|
||||
|
||||
internal bool toBoolean(XPathNodeIterator nodeIterator) {
|
||||
object result = arg.Evaluate(nodeIterator);
|
||||
if (result is XPathNodeIterator) return arg.Advance() != null;
|
||||
if (result is string ) return toBoolean((string)result);
|
||||
if (result is double ) return toBoolean((double)result);
|
||||
if (result is bool ) return (bool)result;
|
||||
Debug.Assert(result is XPathNavigator, "Unknown value type");
|
||||
return true;
|
||||
}
|
||||
|
||||
public override XPathResultType StaticType { get { return XPathResultType.Boolean; } }
|
||||
|
||||
private bool Not(XPathNodeIterator nodeIterator) {
|
||||
return ! (bool) arg.Evaluate(nodeIterator);
|
||||
}
|
||||
|
||||
private bool Lang(XPathNodeIterator nodeIterator) {
|
||||
string str = arg.Evaluate(nodeIterator).ToString();
|
||||
string lang = nodeIterator.Current.XmlLang;
|
||||
return (
|
||||
lang.StartsWith(str, StringComparison.OrdinalIgnoreCase) &&
|
||||
(lang.Length == str.Length || lang[str.Length] == '-')
|
||||
);
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new BooleanFunctions(this); }
|
||||
|
||||
public override void PrintQuery(XmlWriter w) {
|
||||
w.WriteStartElement(this.GetType().Name);
|
||||
w.WriteAttributeString("name", funcType.ToString());
|
||||
if (arg != null) {
|
||||
arg.PrintQuery(w);
|
||||
}
|
||||
w.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="CacheAxisQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal abstract class CacheAxisQuery : BaseAxisQuery {
|
||||
// int count; -- we reusing it here
|
||||
protected List<XPathNavigator> outputBuffer;
|
||||
|
||||
public CacheAxisQuery(Query qyInput, string name, string prefix, XPathNodeType typeTest) : base(qyInput, name, prefix, typeTest) {
|
||||
this.outputBuffer = new List<XPathNavigator>();
|
||||
this.count = 0;
|
||||
}
|
||||
protected CacheAxisQuery(CacheAxisQuery other) : base(other) {
|
||||
this.outputBuffer = new List<XPathNavigator>(other.outputBuffer);
|
||||
this.count = other.count;
|
||||
}
|
||||
|
||||
public override void Reset() {
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
public override object Evaluate(XPathNodeIterator context) {
|
||||
base.Evaluate(context);
|
||||
outputBuffer.Clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
Debug.Assert(0 <= count && count <= outputBuffer.Count);
|
||||
if (count < outputBuffer.Count) {
|
||||
return outputBuffer[count++];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override XPathNavigator Current {
|
||||
get {
|
||||
Debug.Assert(0 <= count && count <= outputBuffer.Count);
|
||||
if (count == 0) {
|
||||
return null;
|
||||
}
|
||||
return outputBuffer[count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public override int CurrentPosition { get { return count; } }
|
||||
public override int Count { get { return outputBuffer.Count; } }
|
||||
public override QueryProps Properties { get { return QueryProps.Merge | QueryProps.Cached | QueryProps.Position | QueryProps.Count; } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="CacheChildrenQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using StackInt = ClonableStack<int>;
|
||||
using StackNav = ClonableStack<System.Xml.XPath.XPathNavigator>;
|
||||
|
||||
// This class implements Children axis on Ancestor & Descendant imputs. (as well as id(), preciding, following)
|
||||
// The problem here is that is descenant::*/child::* and ancestor::*/child::* can produce duplicates nodes
|
||||
// The algorithm havily uses the fact that in our implementation of both AncestorQuery and DecsndantQuery return nodes in document order.
|
||||
// As result first child is always before or equal of next input.
|
||||
// So we don't need to call DecideNextNode() when needInput == true && stack is empty.
|
||||
internal sealed class CacheChildrenQuery : ChildrenQuery {
|
||||
XPathNavigator nextInput = null;
|
||||
StackNav elementStk;
|
||||
StackInt positionStk;
|
||||
bool needInput;
|
||||
#if DEBUG
|
||||
XPathNavigator lastNode = null;
|
||||
#endif
|
||||
|
||||
public CacheChildrenQuery(Query qyInput, string name, string prefix, XPathNodeType type) : base(qyInput, name, prefix, type) {
|
||||
this.elementStk = new StackNav();
|
||||
this.positionStk = new StackInt();
|
||||
this.needInput = true;
|
||||
}
|
||||
private CacheChildrenQuery(CacheChildrenQuery other) : base(other) {
|
||||
this.nextInput = Clone(other.nextInput);
|
||||
this.elementStk = other.elementStk.Clone();
|
||||
this.positionStk = other.positionStk.Clone();
|
||||
this.needInput = other.needInput;
|
||||
#if DEBUG
|
||||
this.lastNode = Clone(other.lastNode);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Reset() {
|
||||
nextInput = null;
|
||||
elementStk.Clear();
|
||||
positionStk.Clear();
|
||||
needInput = true;
|
||||
base.Reset();
|
||||
#if DEBUG
|
||||
lastNode = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
do {
|
||||
if (needInput) {
|
||||
if (elementStk.Count == 0) {
|
||||
currentNode = GetNextInput();
|
||||
if (currentNode == null) {
|
||||
return null;
|
||||
}
|
||||
if (!currentNode.MoveToFirstChild()) {
|
||||
continue;
|
||||
}
|
||||
position = 0;
|
||||
} else {
|
||||
currentNode = elementStk .Pop();
|
||||
position = positionStk.Pop();
|
||||
if (!DecideNextNode()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
needInput = false;
|
||||
} else {
|
||||
if (!currentNode.MoveToNext() || !DecideNextNode()) {
|
||||
needInput = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
if (lastNode != null) {
|
||||
if (currentNode.GetType().ToString() == "Microsoft.VisualStudio.Modeling.StoreNavigator") {
|
||||
XmlNodeOrder order = CompareNodes(lastNode, currentNode);
|
||||
Debug.Assert(order == XmlNodeOrder.Before, "Algorith error. Nodes expected to be DocOrderDistinct");
|
||||
}
|
||||
}
|
||||
lastNode = currentNode.Clone();
|
||||
#endif
|
||||
if (matches(currentNode)) {
|
||||
position++;
|
||||
return currentNode;
|
||||
}
|
||||
} while (true);
|
||||
} // Advance
|
||||
|
||||
private bool DecideNextNode() {
|
||||
nextInput = GetNextInput();
|
||||
if (nextInput != null) {
|
||||
if (CompareNodes(currentNode, nextInput) == XmlNodeOrder.After) {
|
||||
elementStk .Push(currentNode);
|
||||
positionStk.Push(position);
|
||||
currentNode = nextInput;
|
||||
nextInput = null;
|
||||
if (!currentNode.MoveToFirstChild()) {
|
||||
return false;
|
||||
}
|
||||
position = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private XPathNavigator GetNextInput() {
|
||||
XPathNavigator result;
|
||||
if (nextInput != null) {
|
||||
result = nextInput;
|
||||
nextInput = null;
|
||||
} else {
|
||||
result = qyInput.Advance();
|
||||
if (result != null) {
|
||||
result = result.Clone();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new CacheChildrenQuery(this); }
|
||||
} // Children Query}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="CacheOutputQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Xsl;
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal abstract class CacheOutputQuery : Query {
|
||||
internal Query input;
|
||||
// int count; -- we reusing it here
|
||||
protected List<XPathNavigator> outputBuffer;
|
||||
|
||||
public CacheOutputQuery(Query input) {
|
||||
this.input = input;
|
||||
this.outputBuffer = new List<XPathNavigator>();
|
||||
this.count = 0;
|
||||
}
|
||||
protected CacheOutputQuery(CacheOutputQuery other) : base(other) {
|
||||
this.input = Clone(other.input);
|
||||
this.outputBuffer = new List<XPathNavigator>(other.outputBuffer);
|
||||
this.count = other.count;
|
||||
}
|
||||
|
||||
public override void Reset() {
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
public override void SetXsltContext(XsltContext context){
|
||||
input.SetXsltContext(context);
|
||||
}
|
||||
|
||||
public override object Evaluate(XPathNodeIterator context) {
|
||||
outputBuffer.Clear();
|
||||
count = 0;
|
||||
return input.Evaluate(context);// This is trick. IDQuery needs this value. Otherwise we would return this.
|
||||
// All subclasses should and would anyway override thismethod and return this.
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
Debug.Assert(0 <= count && count <= outputBuffer.Count);
|
||||
if (count < outputBuffer.Count) {
|
||||
return outputBuffer[count++];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override XPathNavigator Current {
|
||||
get {
|
||||
Debug.Assert(0 <= count && count <= outputBuffer.Count);
|
||||
if (count == 0) {
|
||||
return null;
|
||||
}
|
||||
return outputBuffer[count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public override XPathResultType StaticType { get { return XPathResultType.NodeSet; } }
|
||||
public override int CurrentPosition { get { return count; } }
|
||||
public override int Count { get { return outputBuffer.Count; } }
|
||||
public override QueryProps Properties { get { return QueryProps.Merge | QueryProps.Cached | QueryProps.Position | QueryProps.Count; } }
|
||||
|
||||
public override void PrintQuery(XmlWriter w) {
|
||||
w.WriteStartElement(this.GetType().Name);
|
||||
input.PrintQuery(w);
|
||||
w.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ChildrenQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Xml.Xsl;
|
||||
using System.Collections;
|
||||
|
||||
internal class ChildrenQuery : BaseAxisQuery {
|
||||
XPathNodeIterator iterator = XPathEmptyIterator.Instance;
|
||||
|
||||
public ChildrenQuery(Query qyInput, string name, string prefix, XPathNodeType type) : base (qyInput, name, prefix, type) {}
|
||||
protected ChildrenQuery(ChildrenQuery other) : base(other) {
|
||||
this.iterator = Clone(other.iterator);
|
||||
}
|
||||
|
||||
public override void Reset() {
|
||||
iterator = XPathEmptyIterator.Instance;
|
||||
base.Reset();
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
while (!iterator.MoveNext()) {
|
||||
XPathNavigator input = qyInput.Advance();
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (NameTest) {
|
||||
if (TypeTest == XPathNodeType.ProcessingInstruction) {
|
||||
iterator = new IteratorFilter(input.SelectChildren(TypeTest), Name);
|
||||
} else {
|
||||
iterator = input.SelectChildren(Name, Namespace);
|
||||
}
|
||||
} else {
|
||||
iterator = input.SelectChildren(TypeTest);
|
||||
}
|
||||
position = 0;
|
||||
}
|
||||
position ++;
|
||||
currentNode = iterator.Current;
|
||||
return currentNode;
|
||||
} // Advance
|
||||
|
||||
public sealed override XPathNavigator MatchNode(XPathNavigator context) {
|
||||
if (context != null) {
|
||||
if (matches(context)) {
|
||||
XPathNavigator temp = context.Clone();
|
||||
if (temp.NodeType != XPathNodeType.Attribute && temp.MoveToParent()) {
|
||||
return qyInput.MatchNode(temp);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new ChildrenQuery(this); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ClonableStack.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal sealed class ClonableStack<T> : System.Collections.Generic.List<T> {
|
||||
|
||||
public ClonableStack() {}
|
||||
public ClonableStack(int capacity) : base(capacity) {}
|
||||
|
||||
private ClonableStack(System.Collections.Generic.IEnumerable<T> collection) : base(collection) { }
|
||||
|
||||
public void Push(T value) {
|
||||
base.Add(value);
|
||||
}
|
||||
|
||||
public T Pop() {
|
||||
int last = base.Count - 1;
|
||||
T result = base[last];
|
||||
base.RemoveAt(last);
|
||||
return result;
|
||||
}
|
||||
|
||||
public T Peek() {
|
||||
return base[base.Count - 1];
|
||||
}
|
||||
|
||||
public ClonableStack<T> Clone() { return new ClonableStack<T>(this); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="CompiledXpathExpr.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Collections;
|
||||
using System.Xml.Xsl;
|
||||
|
||||
internal class CompiledXpathExpr : XPathExpression {
|
||||
Query query;
|
||||
string expr;
|
||||
bool needContext;
|
||||
|
||||
internal CompiledXpathExpr(Query query, string expression, bool needContext) {
|
||||
this.query = query;
|
||||
this.expr = expression;
|
||||
this.needContext = needContext;
|
||||
}
|
||||
|
||||
internal Query QueryTree {
|
||||
get {
|
||||
if (needContext) {
|
||||
throw XPathException.Create(Res.Xp_NoContext);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Expression {
|
||||
get { return expr; }
|
||||
}
|
||||
|
||||
public virtual void CheckErrors() {
|
||||
Debug.Assert(query != null, "In case of error in XPath we create ErrorXPathExpression");
|
||||
}
|
||||
|
||||
public override void AddSort(object expr, IComparer comparer) {
|
||||
// sort makes sense only when we are dealing with a query that
|
||||
// returns a nodeset.
|
||||
Query evalExpr;
|
||||
if (expr is string) {
|
||||
evalExpr = new QueryBuilder().Build((string)expr, out needContext); // this will throw if expr is invalid
|
||||
} else if (expr is CompiledXpathExpr) {
|
||||
evalExpr = ((CompiledXpathExpr)expr).QueryTree;
|
||||
} else {
|
||||
throw XPathException.Create(Res.Xp_BadQueryObject);
|
||||
}
|
||||
SortQuery sortQuery = query as SortQuery;
|
||||
if (sortQuery == null) {
|
||||
query = sortQuery = new SortQuery(query);
|
||||
}
|
||||
sortQuery.AddSort(evalExpr, comparer);
|
||||
}
|
||||
|
||||
public override void AddSort(object expr, XmlSortOrder order, XmlCaseOrder caseOrder, string lang, XmlDataType dataType) {
|
||||
AddSort(expr, new XPathComparerHelper(order, caseOrder, lang, dataType));
|
||||
}
|
||||
|
||||
public override XPathExpression Clone() {
|
||||
return new CompiledXpathExpr(Query.Clone(query), expr, needContext);
|
||||
}
|
||||
|
||||
public override void SetContext(XmlNamespaceManager nsManager) {
|
||||
SetContext((IXmlNamespaceResolver)nsManager);
|
||||
}
|
||||
|
||||
public override void SetContext(IXmlNamespaceResolver nsResolver) {
|
||||
XsltContext xsltContext = nsResolver as XsltContext;
|
||||
if(xsltContext == null) {
|
||||
if(nsResolver == null) {
|
||||
nsResolver = new XmlNamespaceManager(new NameTable());
|
||||
}
|
||||
xsltContext = new UndefinedXsltContext(nsResolver);
|
||||
}
|
||||
query.SetXsltContext(xsltContext);
|
||||
|
||||
needContext = false;
|
||||
}
|
||||
|
||||
public override XPathResultType ReturnType { get { return query.StaticType; } }
|
||||
|
||||
private class UndefinedXsltContext : XsltContext {
|
||||
private IXmlNamespaceResolver nsResolver;
|
||||
|
||||
public UndefinedXsltContext(IXmlNamespaceResolver nsResolver) : base(/*dummy*/false) {
|
||||
this.nsResolver = nsResolver;
|
||||
}
|
||||
//----- Namespace support -----
|
||||
public override string DefaultNamespace {
|
||||
get { return string.Empty; }
|
||||
}
|
||||
public override string LookupNamespace(string prefix) {
|
||||
Debug.Assert(prefix != null);
|
||||
if (prefix.Length == 0) {
|
||||
return string.Empty;
|
||||
}
|
||||
string ns = this.nsResolver.LookupNamespace(prefix);
|
||||
if (ns == null) {
|
||||
throw XPathException.Create(Res.XmlUndefinedAlias, prefix);
|
||||
}
|
||||
return ns;
|
||||
}
|
||||
//----- XsltContext support -----
|
||||
public override IXsltContextVariable ResolveVariable(string prefix, string name) {
|
||||
throw XPathException.Create(Res.Xp_UndefinedXsltContext);
|
||||
}
|
||||
public override IXsltContextFunction ResolveFunction(string prefix, string name, XPathResultType[] ArgTypes) {
|
||||
throw XPathException.Create(Res.Xp_UndefinedXsltContext);
|
||||
}
|
||||
public override bool Whitespace { get{ return false; } }
|
||||
public override bool PreserveWhitespace(XPathNavigator node) { return false; }
|
||||
public override int CompareDocument (string baseUri, string nextbaseUri) {
|
||||
return string.CompareOrdinal(baseUri, nextbaseUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class XPathComparerHelper : IComparer {
|
||||
private XmlSortOrder order;
|
||||
private XmlCaseOrder caseOrder;
|
||||
private CultureInfo cinfo;
|
||||
private XmlDataType dataType;
|
||||
|
||||
public XPathComparerHelper(XmlSortOrder order, XmlCaseOrder caseOrder, string lang, XmlDataType dataType) {
|
||||
if (lang == null) {
|
||||
this.cinfo = System.Threading.Thread.CurrentThread.CurrentCulture;
|
||||
} else {
|
||||
try {
|
||||
this.cinfo = new CultureInfo(lang);
|
||||
}
|
||||
catch (System.ArgumentException) {
|
||||
throw; // Throwing an XsltException would be a breaking change
|
||||
}
|
||||
}
|
||||
|
||||
if (order == XmlSortOrder.Descending) {
|
||||
if (caseOrder == XmlCaseOrder.LowerFirst) {
|
||||
caseOrder = XmlCaseOrder.UpperFirst;
|
||||
}
|
||||
else if (caseOrder == XmlCaseOrder.UpperFirst) {
|
||||
caseOrder = XmlCaseOrder.LowerFirst;
|
||||
}
|
||||
}
|
||||
|
||||
this.order = order;
|
||||
this.caseOrder = caseOrder;
|
||||
this.dataType = dataType;
|
||||
}
|
||||
|
||||
public int Compare(object x, object y) {
|
||||
switch (this.dataType) {
|
||||
case XmlDataType.Text:
|
||||
string s1 = Convert.ToString(x, this.cinfo);
|
||||
string s2 = Convert.ToString(y, this.cinfo);
|
||||
int result = string.Compare(s1, s2, /*ignoreCase:*/ this.caseOrder != XmlCaseOrder.None, this.cinfo);
|
||||
|
||||
if (result != 0 || this.caseOrder == XmlCaseOrder.None)
|
||||
return (this.order == XmlSortOrder.Ascending) ? result : -result;
|
||||
|
||||
// If we came this far, it means that strings s1 and s2 are
|
||||
// equal to each other when case is ignored. Now it's time to check
|
||||
// and see if they differ in case only and take into account the user
|
||||
// requested case order for sorting purposes.
|
||||
result = string.Compare(s1, s2, /*ignoreCase:*/ false, this.cinfo);
|
||||
return (this.caseOrder == XmlCaseOrder.LowerFirst) ? result : -result;
|
||||
|
||||
case XmlDataType.Number:
|
||||
double r1 = XmlConvert.ToXPathDouble(x);
|
||||
double r2 = XmlConvert.ToXPathDouble(y);
|
||||
result = r1.CompareTo(r2);
|
||||
return (this.order == XmlSortOrder.Ascending) ? result : -result;
|
||||
|
||||
default:
|
||||
// dataType doesn't support any other value
|
||||
throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
|
||||
}
|
||||
} // Compare ()
|
||||
} // class XPathComparerHelper
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ContextQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal class ContextQuery : Query {
|
||||
protected XPathNavigator contextNode;
|
||||
|
||||
public ContextQuery() {
|
||||
this.count = 0;
|
||||
}
|
||||
protected ContextQuery(ContextQuery other) : base(other) {
|
||||
this.contextNode = other.contextNode; // Don't need to clone here
|
||||
}
|
||||
public override void Reset() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
public override XPathNavigator Current { get { return contextNode; } }
|
||||
|
||||
public override object Evaluate(XPathNodeIterator context) {
|
||||
contextNode = context.Current; // We don't clone here. Because we never move it.
|
||||
count = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
if (count == 0) {
|
||||
count = 1;
|
||||
return contextNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override XPathNavigator MatchNode(XPathNavigator current) {
|
||||
return current;
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new ContextQuery(this); }
|
||||
|
||||
public override XPathResultType StaticType { get { return XPathResultType.NodeSet; } }
|
||||
public override int CurrentPosition { get { return count; } }
|
||||
public override int Count { get { return 1; } }
|
||||
public override QueryProps Properties { get { return QueryProps.Merge | QueryProps.Cached | QueryProps.Position | QueryProps.Count; } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DescendantQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal abstract class DescendantBaseQuery : BaseAxisQuery {
|
||||
protected bool matchSelf;
|
||||
protected bool abbrAxis;
|
||||
|
||||
public DescendantBaseQuery(Query qyParent, string Name, string Prefix, XPathNodeType Type, bool matchSelf, bool abbrAxis) : base(qyParent, Name, Prefix, Type) {
|
||||
this.matchSelf = matchSelf;
|
||||
this.abbrAxis = abbrAxis;
|
||||
}
|
||||
public DescendantBaseQuery(DescendantBaseQuery other) : base(other) {
|
||||
this.matchSelf = other.matchSelf;
|
||||
this.abbrAxis = other.abbrAxis;
|
||||
}
|
||||
|
||||
public override XPathNavigator MatchNode(XPathNavigator context) {
|
||||
if (context != null) {
|
||||
if (!abbrAxis) {
|
||||
throw XPathException.Create(Res.Xp_InvalidPattern);
|
||||
}
|
||||
XPathNavigator result = null;
|
||||
if (matches(context)) {
|
||||
if (matchSelf) {
|
||||
if ((result = qyInput.MatchNode(context)) != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
XPathNavigator anc = context.Clone();
|
||||
while (anc.MoveToParent()) {
|
||||
if ((result = qyInput.MatchNode(anc)) != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void PrintQuery(XmlWriter w) {
|
||||
w.WriteStartElement(this.GetType().Name);
|
||||
if (matchSelf) {
|
||||
w.WriteAttributeString("self", "yes");
|
||||
}
|
||||
if (NameTest) {
|
||||
w.WriteAttributeString("name", Prefix.Length != 0 ? Prefix + ':' + Name : Name);
|
||||
}
|
||||
if (TypeTest != XPathNodeType.Element) {
|
||||
w.WriteAttributeString("nodeType", TypeTest.ToString());
|
||||
}
|
||||
qyInput.PrintQuery(w);
|
||||
w.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DescendantQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal class DescendantQuery : DescendantBaseQuery {
|
||||
XPathNodeIterator nodeIterator;
|
||||
|
||||
internal DescendantQuery(Query qyParent, string Name, string Prefix, XPathNodeType Type, bool matchSelf, bool abbrAxis)
|
||||
: base(qyParent, Name, Prefix, Type, matchSelf, abbrAxis) {}
|
||||
|
||||
public DescendantQuery(DescendantQuery other) : base(other) {
|
||||
this.nodeIterator = Clone(other.nodeIterator);
|
||||
}
|
||||
|
||||
public override void Reset() {
|
||||
nodeIterator = null;
|
||||
base.Reset();
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
while (true) {
|
||||
if (nodeIterator == null) {
|
||||
position = 0;
|
||||
XPathNavigator nav = qyInput.Advance();
|
||||
if (nav == null) {
|
||||
return null;
|
||||
}
|
||||
if (NameTest) {
|
||||
if (TypeTest == XPathNodeType.ProcessingInstruction) {
|
||||
nodeIterator = new IteratorFilter(nav.SelectDescendants(TypeTest, matchSelf), Name);
|
||||
} else {
|
||||
nodeIterator = nav.SelectDescendants(Name, Namespace, matchSelf);
|
||||
}
|
||||
} else {
|
||||
nodeIterator = nav.SelectDescendants(TypeTest, matchSelf);
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeIterator.MoveNext()) {
|
||||
position++;
|
||||
currentNode = nodeIterator.Current;
|
||||
return currentNode;
|
||||
} else {
|
||||
nodeIterator = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new DescendantQuery(this); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DescendantOverDescendantQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
|
||||
// DescendantOverDescendantQuery: for each input it looks for the topmost descendents that matches to ns:name
|
||||
// This is posible when query which has this query as its input (child query) is descendent as well.
|
||||
// Work of this query doesn't depend on DOD of its input.
|
||||
// It doesn't garate DOD of the output even when input is DOD.
|
||||
internal sealed class DescendantOverDescendantQuery : DescendantBaseQuery {
|
||||
private int level = 0;
|
||||
|
||||
public DescendantOverDescendantQuery(Query qyParent, bool matchSelf, string name, string prefix, XPathNodeType typeTest, bool abbrAxis) :
|
||||
base(qyParent, name, prefix, typeTest, matchSelf, abbrAxis) {}
|
||||
private DescendantOverDescendantQuery(DescendantOverDescendantQuery other) : base(other) {
|
||||
this.level = other.level;
|
||||
}
|
||||
|
||||
public override void Reset() {
|
||||
level = 0;
|
||||
base.Reset();
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
while (true) {
|
||||
if (level == 0) {
|
||||
currentNode = qyInput.Advance();
|
||||
position = 0;
|
||||
if (currentNode == null) {
|
||||
return null;
|
||||
}
|
||||
if (matchSelf && matches(currentNode)) {
|
||||
position = 1;
|
||||
return currentNode;
|
||||
}
|
||||
currentNode = currentNode.Clone();
|
||||
if (! MoveToFirstChild()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!MoveUpUntillNext()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
do {
|
||||
if (matches(currentNode)) {
|
||||
position++;
|
||||
return currentNode;
|
||||
}
|
||||
} while (MoveToFirstChild());
|
||||
}
|
||||
}
|
||||
|
||||
private bool MoveToFirstChild() {
|
||||
if (currentNode.MoveToFirstChild()) {
|
||||
level++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool MoveUpUntillNext() { // move up untill we can move next
|
||||
while (! currentNode.MoveToNext()) {
|
||||
-- level;
|
||||
if (level == 0) {
|
||||
return false;
|
||||
}
|
||||
bool result = currentNode.MoveToParent();
|
||||
Debug.Assert(result, "Algorithm error, We always should be able to move up if level > 0");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new DescendantOverDescendantQuery(this); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DocumentOrderQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal sealed class DocumentOrderQuery : CacheOutputQuery {
|
||||
|
||||
public DocumentOrderQuery(Query qyParent) : base(qyParent) {}
|
||||
private DocumentOrderQuery(DocumentOrderQuery other) : base(other) { }
|
||||
|
||||
public override object Evaluate(XPathNodeIterator context) {
|
||||
base.Evaluate(context);
|
||||
|
||||
XPathNavigator node;
|
||||
while ((node = base.input.Advance()) != null) {
|
||||
Insert(outputBuffer, node);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public override XPathNavigator MatchNode(XPathNavigator context) {
|
||||
return input.MatchNode(context);
|
||||
}
|
||||
|
||||
public override XPathNodeIterator Clone() { return new DocumentOrderQuery(this); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="EmptyQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Xml.Xsl;
|
||||
using System.Collections;
|
||||
|
||||
internal sealed class EmptyQuery : Query {
|
||||
public override XPathNavigator Advance() { return null; }
|
||||
public override XPathNodeIterator Clone() { return this; }
|
||||
public override object Evaluate(XPathNodeIterator context) { return this; }
|
||||
public override int CurrentPosition { get { return 0; } }
|
||||
public override int Count { get { return 0; } }
|
||||
public override QueryProps Properties { get { return QueryProps.Merge | QueryProps.Cached | QueryProps.Position | QueryProps.Count; } }
|
||||
public override XPathResultType StaticType { get { return XPathResultType.NodeSet; } }
|
||||
public override void Reset() { }
|
||||
public override XPathNavigator Current { get { return null; } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ExtensionQuery.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace MS.Internal.Xml.XPath {
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.Xsl;
|
||||
using System.Xml.XPath;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Collections;
|
||||
|
||||
internal abstract class ExtensionQuery : Query {
|
||||
protected string prefix;
|
||||
protected string name;
|
||||
protected XsltContext xsltContext;
|
||||
private ResetableIterator queryIterator;
|
||||
|
||||
public ExtensionQuery(string prefix, string name) : base() {
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
}
|
||||
protected ExtensionQuery(ExtensionQuery other) : base(other) {
|
||||
this.prefix = other.prefix;
|
||||
this.name = other.name;
|
||||
this.xsltContext = other.xsltContext;
|
||||
this.queryIterator = (ResetableIterator)Clone(other.queryIterator);
|
||||
}
|
||||
|
||||
public override void Reset() {
|
||||
if (queryIterator != null) {
|
||||
queryIterator.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public override XPathNavigator Current {
|
||||
get {
|
||||
if (queryIterator == null) {
|
||||
throw XPathException.Create(Res.Xp_NodeSetExpected);
|
||||
}
|
||||
if (queryIterator.CurrentPosition == 0) {
|
||||
Advance();
|
||||
}
|
||||
return queryIterator.Current;
|
||||
}
|
||||
}
|
||||
|
||||
public override XPathNavigator Advance() {
|
||||
if (queryIterator == null) {
|
||||
throw XPathException.Create(Res.Xp_NodeSetExpected);
|
||||
}
|
||||
if (queryIterator.MoveNext()) {
|
||||
return queryIterator.Current;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override int CurrentPosition {
|
||||
get {
|
||||
if (queryIterator != null) {
|
||||
return queryIterator.CurrentPosition;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected object ProcessResult(object value) {
|
||||
if (value is string ) return value;
|
||||
if (value is double ) return value;
|
||||
if (value is bool ) return value;
|
||||
if (value is XPathNavigator) return value;
|
||||
if (value is Int32 ) return (double)(Int32)value;
|
||||
|
||||
if (value == null) {
|
||||
queryIterator = XPathEmptyIterator.Instance;
|
||||
return this; // We map null to NodeSet to let $null/foo work well.
|
||||
}
|
||||
|
||||
ResetableIterator resetable = value as ResetableIterator;
|
||||
if (resetable != null) {
|
||||
// We need Clone() value because variable may be used several times
|
||||
// and they shouldn't
|
||||
queryIterator = (ResetableIterator)resetable.Clone();
|
||||
return this;
|
||||
}
|
||||
XPathNodeIterator nodeIterator = value as XPathNodeIterator;
|
||||
if (nodeIterator != null) {
|
||||
queryIterator = new XPathArrayIterator(nodeIterator);
|
||||
return this;
|
||||
}
|
||||
IXPathNavigable navigable = value as IXPathNavigable;
|
||||
if(navigable != null) {
|
||||
return navigable.CreateNavigator();
|
||||
}
|
||||
|
||||
if (value is Int16 ) return (double)(Int16)value;
|
||||
if (value is Int64 ) return (double)(Int64)value;
|
||||
if (value is UInt32) return (double)(UInt32)value;
|
||||
if (value is UInt16) return (double)(UInt16)value;
|
||||
if (value is UInt64) return (double)(UInt64)value;
|
||||
if (value is Single) return (double)(Single)value;
|
||||
if (value is Decimal) return (double)(Decimal)value;
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
protected string QName { get { return prefix.Length != 0 ? prefix + ":" + name : name; } }
|
||||
|
||||
public override int Count { get { return queryIterator == null ? 1 : queryIterator.Count; } }
|
||||
public override XPathResultType StaticType { get { return XPathResultType.Any; } }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user