Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / XLinq / System / Xml / Linq / XNodeNavigator.cs / 1 / XNodeNavigator.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
namespace System.Xml.XPath
{
internal class XNodeNavigator : XPathNavigator, IXmlLineInfo
{
const int DocumentContentMask =
(1 << (int)XmlNodeType.Element) |
(1 << (int)XmlNodeType.ProcessingInstruction) |
(1 << (int)XmlNodeType.Comment);
static readonly int[] ElementContentMasks = {
0, // Root
(1 << (int)XmlNodeType.Element), // Element
0, // Attribute
0, // Namespace
(1 << (int)XmlNodeType.CDATA) |
(1 << (int)XmlNodeType.Text), // Text
0, // SignificantWhitespace
0, // Whitespace
(1 << (int)XmlNodeType.ProcessingInstruction), // ProcessingInstruction
(1 << (int)XmlNodeType.Comment), // Comment
(1 << (int)XmlNodeType.Element) |
(1 << (int)XmlNodeType.CDATA) |
(1 << (int)XmlNodeType.Text) |
(1 << (int)XmlNodeType.ProcessingInstruction) |
(1 << (int)XmlNodeType.Comment) // All
};
const int TextMask =
(1 << (int)XmlNodeType.CDATA) |
(1 << (int)XmlNodeType.Text);
static XAttribute XmlNamespaceDeclaration;
// The navigator position is encoded by the tuple (source, parent).
// Lazy text uses (instance, parent element). Namespace declaration uses
// (instance, parent element). Common XObjects uses (instance, null).
object source;
XElement parent;
XmlNameTable nameTable;
public XNodeNavigator(XNode node, XmlNameTable nameTable) {
this.source = node;
this.nameTable = nameTable != null ? nameTable : CreateNameTable();
}
public XNodeNavigator(XNodeNavigator other) {
source = other.source;
parent = other.parent;
nameTable = other.nameTable;
}
public override string BaseURI {
get {
XObject o = source as XObject;
if (o != null) {
return o.BaseUri;
}
if (parent != null) {
return parent.BaseUri;
}
return string.Empty;
}
}
public override bool HasAttributes {
get {
XElement e = source as XElement;
if (e != null) {
XAttribute a = e.lastAttr;
if (a != null) {
do {
a = a.next;
if (!a.IsNamespaceDeclaration) {
return true;
}
} while (a != e.lastAttr);
}
}
return false;
}
}
public override bool HasChildren {
get {
XContainer c = source as XContainer;
if (c != null && c.content != null) {
XNode n = c.content as XNode;
if (n != null) {
do {
n = n.next;
if (IsContent(c, n)) {
return true;
}
} while (n != c.content);
return false;
}
string s = (string)c.content;
if (s.Length != 0 && (c.parent != null || c is XElement)) {
return true;
}
}
return false;
}
}
public override bool IsEmptyElement {
get {
XElement e = source as XElement;
return e != null && e.IsEmpty;
}
}
public override string LocalName {
get { return nameTable.Add(GetLocalName()); }
}
string GetLocalName() {
XElement e = source as XElement;
if (e != null) {
return e.Name.LocalName;
}
XAttribute a = source as XAttribute;
if (a != null) {
if (parent != null && a.Name.NamespaceName.Length == 0) {
return string.Empty; // backcompat
}
return a.Name.LocalName;
}
XProcessingInstruction p = source as XProcessingInstruction;
if (p != null) {
return p.Target;
}
return string.Empty;
}
public override string Name {
get {
string prefix = GetPrefix();
if (prefix.Length == 0) {
return nameTable.Add(GetLocalName());
}
return nameTable.Add(string.Concat(prefix, ":", GetLocalName()));
}
}
public override string NamespaceURI {
get { return nameTable.Add(GetNamespaceURI()); }
}
string GetNamespaceURI() {
XElement e = source as XElement;
if (e != null) {
return e.Name.NamespaceName;
}
XAttribute a = source as XAttribute;
if (a != null) {
if (parent != null) {
return string.Empty; // backcompat
}
return a.Name.NamespaceName;
}
return string.Empty;
}
public override XmlNameTable NameTable {
get { return nameTable; }
}
public override XPathNodeType NodeType {
get {
XObject o = source as XObject;
if (o != null) {
switch (o.NodeType) {
case XmlNodeType.Element:
return XPathNodeType.Element;
case XmlNodeType.Attribute:
if (parent != null) {
return XPathNodeType.Namespace;
}
return XPathNodeType.Attribute;
case XmlNodeType.Document:
return XPathNodeType.Root;
case XmlNodeType.Comment:
return XPathNodeType.Comment;
case XmlNodeType.ProcessingInstruction:
return XPathNodeType.ProcessingInstruction;
default:
return XPathNodeType.Text;
}
}
return XPathNodeType.Text;
}
}
public override string Prefix {
get { return nameTable.Add(GetPrefix()); }
}
string GetPrefix() {
XElement e = source as XElement;
if (e != null) {
string prefix = e.GetPrefixOfNamespace(e.Name.Namespace);
if (prefix != null) {
return prefix;
}
return string.Empty;
}
XAttribute a = source as XAttribute;
if (a != null) {
if (parent != null) {
return string.Empty; // backcompat
}
string prefix = a.GetPrefixOfNamespace(a.Name.Namespace);
if (prefix != null) {
return prefix;
}
}
return string.Empty;
}
public override object UnderlyingObject {
get {
if (source is string) {
// convert lazy text to eager text
source = parent.LastNode;
parent = null;
}
return source;
}
}
public override string Value {
get {
XObject o = source as XObject;
if (o != null) {
switch (o.NodeType) {
case XmlNodeType.Element:
return ((XElement)o).Value;
case XmlNodeType.Attribute:
return ((XAttribute)o).Value;
case XmlNodeType.Document:
XElement root = ((XDocument)o).Root;
return root != null ? root.Value : string.Empty;
case XmlNodeType.Text:
case XmlNodeType.CDATA:
return CollectText((XText)o);
case XmlNodeType.Comment:
return ((XComment)o).Value;
case XmlNodeType.ProcessingInstruction:
return ((XProcessingInstruction)o).Data;
default:
return string.Empty;
}
}
return (string)source;
}
}
public override bool CheckValidity(System.Xml.Schema.XmlSchemaSet schemas, System.Xml.Schema.ValidationEventHandler validationEventHandler) {
throw new NotSupportedException(Res.GetString(Res.NotSupported_CheckValidity));
}
public override XPathNavigator Clone() {
return new XNodeNavigator(this);
}
public override bool IsSamePosition(XPathNavigator navigator) {
XNodeNavigator other = navigator as XNodeNavigator;
if (other == null) {
return false;
}
return IsSamePosition(this, other);
}
public override bool MoveTo(XPathNavigator navigator) {
XNodeNavigator other = navigator as XNodeNavigator;
if (other != null) {
source = other.source;
parent = other.parent;
return true;
}
return false;
}
public override bool MoveToAttribute(string localName, string namespaceName) {
XElement e = source as XElement;
if (e != null) {
XAttribute a = e.lastAttr;
if (a != null) {
do {
a = a.next;
if (a.Name.LocalName == localName &&
a.Name.NamespaceName == namespaceName &&
!a.IsNamespaceDeclaration) {
source = a;
return true;
}
} while (a != e.lastAttr);
}
}
return false;
}
public override bool MoveToChild(string localName, string namespaceName) {
XContainer c = source as XContainer;
if (c != null && c.content != null) {
XNode n = c.content as XNode;
if (n != null) {
do {
n = n.next;
XElement e = n as XElement;
if (e != null &&
e.Name.LocalName == localName &&
e.Name.NamespaceName == namespaceName) {
source = e;
return true;
}
} while (n != c.content);
}
}
return false;
}
public override bool MoveToChild(XPathNodeType type) {
XContainer c = source as XContainer;
if (c != null && c.content != null) {
XNode n = c.content as XNode;
if (n != null) {
int mask = GetElementContentMask(type);
if ((TextMask & mask) != 0 && c.parent == null && c is XDocument) {
mask &= ~TextMask;
}
do {
n = n.next;
if (((1 << (int)n.NodeType) & mask) != 0) {
source = n;
return true;
}
} while (n != c.content);
return false;
}
string s = (string)c.content;
if (s.Length != 0) {
int mask = GetElementContentMask(type);
if ((TextMask & mask) != 0 && c.parent == null && c is XDocument) {
return false;
}
if (((1 << (int)XmlNodeType.Text) & mask) != 0) {
source = s;
parent = (XElement)c;
return true;
}
}
}
return false;
}
public override bool MoveToFirstAttribute() {
XElement e = source as XElement;
if (e != null) {
XAttribute a = e.lastAttr;
if (a != null) {
do {
a = a.next;
if (!a.IsNamespaceDeclaration) {
source = a;
return true;
}
} while (a != e.lastAttr);
}
}
return false;
}
public override bool MoveToFirstChild() {
XContainer c = source as XContainer;
if (c != null && c.content != null) {
XNode n = c.content as XNode;
if (n != null) {
do {
n = n.next;
if (IsContent(c, n)) {
source = n;
return true;
}
} while (n != c.content);
return false;
}
string s = (string)c.content;
if (s.Length != 0 && (c.parent != null || c is XElement)) {
source = s;
parent = (XElement)c;
return true;
}
}
return false;
}
public override bool MoveToFirstNamespace(XPathNamespaceScope scope) {
XElement e = source as XElement;
if (e != null) {
XAttribute a = null;
switch (scope) {
case XPathNamespaceScope.Local:
a = GetFirstNamespaceDeclarationLocal(e);
break;
case XPathNamespaceScope.ExcludeXml:
a = GetFirstNamespaceDeclarationGlobal(e);
while (a != null && a.Name.LocalName == "xml") {
a = GetNextNamespaceDeclarationGlobal(a);
}
break;
case XPathNamespaceScope.All:
a = GetFirstNamespaceDeclarationGlobal(e);
if (a == null) {
a = GetXmlNamespaceDeclaration();
}
break;
}
if (a != null) {
source = a;
parent = e;
return true;
}
}
return false;
}
public override bool MoveToId(string id) {
throw new NotSupportedException(Res.GetString(Res.NotSupported_MoveToId));
}
public override bool MoveToNamespace(string localName) {
XElement e = source as XElement;
if (e != null) {
if (localName == "xmlns") {
return false; // backcompat
}
if (localName != null && localName.Length == 0) {
localName = "xmlns"; // backcompat
}
XAttribute a = GetFirstNamespaceDeclarationGlobal(e);
while (a != null) {
if (a.Name.LocalName == localName) {
source = a;
parent = e;
return true;
}
a = GetNextNamespaceDeclarationGlobal(a);
}
if (localName == "xml") {
source = GetXmlNamespaceDeclaration();
parent = e;
return true;
}
}
return false;
}
public override bool MoveToNext() {
XNode n = source as XNode;
if (n != null) {
XContainer c = n.parent;
if (c != null && n != c.content) {
do {
XNode next = n.next;
if (IsContent(c, next) && !(n is XText && next is XText)) {
source = next;
return true;
}
n = next;
} while (n != c.content);
}
}
return false;
}
public override bool MoveToNext(string localName, string namespaceName) {
XNode n = source as XNode;
if (n != null) {
XContainer c = n.parent;
if (c != null && n != c.content) {
do {
n = n.next;
XElement e = n as XElement;
if (e != null &&
e.Name.LocalName == localName &&
e.Name.NamespaceName == namespaceName) {
source = e;
return true;
}
} while (n != c.content);
}
}
return false;
}
public override bool MoveToNext(XPathNodeType type) {
XNode n = source as XNode;
if (n != null) {
XContainer c = n.parent;
if (c != null && n != c.content) {
int mask = GetElementContentMask(type);
if ((TextMask & mask) != 0 && c.parent == null && c is XDocument) {
mask &= ~TextMask;
}
do {
XNode next = n.next;
if (((1 << (int)next.NodeType) & mask) != 0 && !(n is XText && next is XText)) {
source = next;
return true;
}
n = next;
} while (n != c.content);
}
}
return false;
}
public override bool MoveToNextAttribute() {
XAttribute a = source as XAttribute;
if (a != null && parent == null) {
XElement e = (XElement)a.parent;
if (e != null) {
while (a != e.lastAttr) {
a = a.next;
if (!a.IsNamespaceDeclaration) {
source = a;
return true;
}
}
}
}
return false;
}
public override bool MoveToNextNamespace(XPathNamespaceScope scope) {
XAttribute a = source as XAttribute;
if (a != null && parent != null && !IsXmlNamespaceDeclaration(a)) {
switch (scope) {
case XPathNamespaceScope.Local:
if (a.parent != parent) {
return false;
}
a = GetNextNamespaceDeclarationLocal(a);
break;
case XPathNamespaceScope.ExcludeXml:
do {
a = GetNextNamespaceDeclarationGlobal(a);
} while (a != null &&
(a.Name.LocalName == "xml" ||
HasNamespaceDeclarationInScope(a, parent)));
break;
case XPathNamespaceScope.All:
do {
a = GetNextNamespaceDeclarationGlobal(a);
} while (a != null &&
HasNamespaceDeclarationInScope(a, parent));
if (a == null &&
!HasNamespaceDeclarationInScope(GetXmlNamespaceDeclaration(), parent)) {
a = GetXmlNamespaceDeclaration();
}
break;
}
if (a != null) {
source = a;
return true;
}
}
return false;
}
public override bool MoveToParent() {
if (parent != null) {
source = parent;
parent = null;
return true;
}
XObject o = (XObject)source;
if (o.parent != null) {
source = o.parent;
return true;
}
return false;
}
public override bool MoveToPrevious() {
XNode n = source as XNode;
if (n != null) {
XContainer c = n.parent;
if (c != null) {
XNode q = (XNode)c.content;
if (q.next != n) {
XNode p = null;
do {
q = q.next;
if (IsContent(c, q)) {
p = p is XText && q is XText ? p : q;
}
} while (q.next != n);
if (p != null) {
source = p;
return true;
}
}
}
}
return false;
}
public override XmlReader ReadSubtree() {
XContainer c = source as XContainer;
if (c == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_BadNodeType, NodeType));
return new XNodeReader(c, nameTable);
}
bool IXmlLineInfo.HasLineInfo() {
IXmlLineInfo li = source as IXmlLineInfo;
if (li != null) {
return li.HasLineInfo();
}
return false;
}
int IXmlLineInfo.LineNumber {
get {
IXmlLineInfo li = source as IXmlLineInfo;
if (li != null) {
return li.LineNumber;
}
return 0;
}
}
int IXmlLineInfo.LinePosition {
get {
IXmlLineInfo li = source as IXmlLineInfo;
if (li != null) {
return li.LinePosition;
}
return 0;
}
}
static string CollectText(XText n) {
string s = n.Value;
if (n.parent != null) {
while (n != n.parent.content) {
n = n.next as XText;
if (n == null) break;
s += n.Value;
}
}
return s;
}
static XmlNameTable CreateNameTable() {
XmlNameTable nameTable = new NameTable();
nameTable.Add(string.Empty);
nameTable.Add(XNamespace.xmlnsPrefixNamespace);
nameTable.Add(XNamespace.xmlPrefixNamespace);
return nameTable;
}
static bool IsContent(XContainer c, XNode n) {
if (c.parent != null || c is XElement) {
return true;
}
return ((1 << (int)n.NodeType) & DocumentContentMask) != 0;
}
static bool IsSamePosition(XNodeNavigator n1, XNodeNavigator n2) {
if (n1.source == n2.source && n1.parent == n2.parent) {
return true;
}
// compare lazy text with eager text
if (n1.parent != null ^ n2.parent != null) {
XText t1 = n1.source as XText;
if (t1 != null) {
return (object)t1.Value == (object)n2.source && t1.parent == n2.parent;
}
XText t2 = n2.source as XText;
if (t2 != null) {
return (object)t2.Value == (object)n1.source && t2.parent == n1.parent;
}
}
return false;
}
static bool IsXmlNamespaceDeclaration(XAttribute a) {
return (object)a == (object)GetXmlNamespaceDeclaration();
}
static int GetElementContentMask(XPathNodeType type) {
return ElementContentMasks[(int)type];
}
static XAttribute GetFirstNamespaceDeclarationGlobal(XElement e) {
do {
XAttribute a = GetFirstNamespaceDeclarationLocal(e);
if (a != null) {
return a;
}
e = e.parent as XElement;
} while (e != null);
return null;
}
static XAttribute GetFirstNamespaceDeclarationLocal(XElement e) {
XAttribute a = e.lastAttr;
if (a != null) {
do {
a = a.next;
if (a.IsNamespaceDeclaration) {
return a;
}
} while (a != e.lastAttr);
}
return null;
}
static XAttribute GetNextNamespaceDeclarationGlobal(XAttribute a) {
XElement e = (XElement)a.parent;
if (e == null) {
return null;
}
XAttribute next = GetNextNamespaceDeclarationLocal(a);
if (next != null) {
return next;
}
e = e.parent as XElement;
if (e == null) {
return null;
}
return GetFirstNamespaceDeclarationGlobal(e);
}
static XAttribute GetNextNamespaceDeclarationLocal(XAttribute a) {
XElement e = (XElement)a.parent;
if (e == null) {
return null;
}
while (a != e.lastAttr) {
a = a.next;
if (a.IsNamespaceDeclaration) {
return a;
}
}
return null;
}
static XAttribute GetXmlNamespaceDeclaration() {
if (XmlNamespaceDeclaration == null) {
System.Threading.Interlocked.CompareExchange(ref XmlNamespaceDeclaration, new XAttribute(XNamespace.Xmlns.GetName("xml"), XNamespace.xmlPrefixNamespace), null);
}
return XmlNamespaceDeclaration;
}
static bool HasNamespaceDeclarationInScope(XAttribute a, XElement e) {
XName name = a.Name;
while (e != null && e != a.parent) {
if (e.Attribute(name) != null) {
return true;
}
e = e.parent as XElement;
}
return false;
}
}
struct XPathEvaluator
{
public object Evaluate(XNode node, string expression, IXmlNamespaceResolver resolver) where T : class {
XPathNavigator navigator = node.CreateNavigator();
object result = navigator.Evaluate(expression, resolver);
if (result is XPathNodeIterator) {
return EvaluateIterator((XPathNodeIterator)result);
}
if (!(result is T)) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnexpectedEvaluation, result.GetType()));
return (T)result;
}
IEnumerable EvaluateIterator(XPathNodeIterator result) {
foreach (XPathNavigator navigator in result) {
object r = navigator.UnderlyingObject;
if (!(r is T)) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnexpectedEvaluation, r.GetType()));
yield return (T)r;
XText t = r as XText;
if (t != null && t.parent != null) {
while (t != t.parent.content) {
t = t.next as XText;
if (t == null) break;
yield return (T)(object)t;
}
}
}
}
}
///
/// Extension methods
///
public static class Extensions
{
///
/// Creates an for a given
///
/// Extension point
/// An
public static XPathNavigator CreateNavigator(this XNode node) {
return node.CreateNavigator(null);
}
///
/// Creates an for a given
///
/// Extension point
/// The to be used by
/// the
/// An
public static XPathNavigator CreateNavigator(this XNode node, XmlNameTable nameTable) {
if (node == null) throw new ArgumentNullException("node");
if (node is XDocumentType) throw new ArgumentException(Res.GetString(Res.Argument_CreateNavigator, XmlNodeType.DocumentType));
XText text = node as XText;
if (text != null) {
if (text.parent is XDocument) throw new ArgumentException(Res.GetString(Res.Argument_CreateNavigator, XmlNodeType.Whitespace));
node = CalibrateText(text);
}
return new XNodeNavigator(node, nameTable);
}
///
/// Evaluates an XPath expression
///
/// Extension point
/// The XPath expression
/// The result of evaluating the expression which can be typed as bool, double, string or
/// IEnumerable
public static object XPathEvaluate(this XNode node, string expression) {
return node.XPathEvaluate(expression, null);
}
///
/// Evaluates an XPath expression
///
/// Extension point
/// The XPath expression
/// A for the namespace
/// prefixes used in the XPath expression
/// The result of evaluating the expression which can be typed as bool, double, string or
/// IEnumerable
public static object XPathEvaluate(this XNode node, string expression, IXmlNamespaceResolver resolver) {
if (node == null) throw new ArgumentNullException("node");
return new XPathEvaluator().Evaluate
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AdapterUtil.cs
- PeerInvitationResponse.cs
- BuiltInPermissionSets.cs
- InfoCardRSAPKCS1SignatureFormatter.cs
- ListViewItemCollectionEditor.cs
- ThreadSafeList.cs
- IPAddress.cs
- DataContractSerializerFaultFormatter.cs
- StorageEntitySetMapping.cs
- LinkedResourceCollection.cs
- NotifyParentPropertyAttribute.cs
- CatchDesigner.xaml.cs
- RuleProcessor.cs
- LightweightCodeGenerator.cs
- LocalizedNameDescriptionPair.cs
- MarkerProperties.cs
- PageCodeDomTreeGenerator.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- DefaultBinder.cs
- BindValidationContext.cs
- BuildProvider.cs
- TempEnvironment.cs
- DeclaredTypeValidator.cs
- PropertyManager.cs
- ObfuscationAttribute.cs
- XmlMapping.cs
- MessageFilterException.cs
- HttpHeaderCollection.cs
- EncoderNLS.cs
- ElementUtil.cs
- WebEventTraceProvider.cs
- XpsFontSerializationService.cs
- BinaryMethodMessage.cs
- DataGridViewRowEventArgs.cs
- RelationshipConstraintValidator.cs
- DataGridViewColumn.cs
- Permission.cs
- ListViewItemMouseHoverEvent.cs
- ListViewHitTestInfo.cs
- AtomContentProperty.cs
- LineServicesCallbacks.cs
- Win32Native.cs
- CodeAssignStatement.cs
- VerbConverter.cs
- FusionWrap.cs
- XmlNamespaceDeclarationsAttribute.cs
- ApplicationId.cs
- DataError.cs
- MachineKeySection.cs
- TextureBrush.cs
- XmlToDatasetMap.cs
- DesignTimeData.cs
- Point3DCollection.cs
- EntityDataSourceSelectedEventArgs.cs
- DataTrigger.cs
- VirtualPathUtility.cs
- StorageMappingFragment.cs
- EventNotify.cs
- LayoutEditorPart.cs
- ISAPIRuntime.cs
- ValueQuery.cs
- SingleSelectRootGridEntry.cs
- MemoryMappedView.cs
- ListBoxChrome.cs
- DropDownButton.cs
- CodeGenerator.cs
- BuildTopDownAttribute.cs
- FontUnit.cs
- DesignerFrame.cs
- BamlBinaryWriter.cs
- Fonts.cs
- TextRangeProviderWrapper.cs
- DataGridTextBoxColumn.cs
- DataTableMappingCollection.cs
- columnmapfactory.cs
- UInt32.cs
- AppDomain.cs
- SerializationUtility.cs
- TableRow.cs
- PartitionResolver.cs
- keycontainerpermission.cs
- XmlCharType.cs
- InlineObject.cs
- PolicyException.cs
- Stream.cs
- CompilerParameters.cs
- SqlRowUpdatedEvent.cs
- PathSegment.cs
- MetadataArtifactLoaderXmlReaderWrapper.cs
- WebPartDescription.cs
- RightNameExpirationInfoPair.cs
- DesignerVerbCollection.cs
- GenerateScriptTypeAttribute.cs
- DataBoundControlDesigner.cs
- FilterEventArgs.cs
- TextEditorParagraphs.cs
- Vector3DCollection.cs
- Timer.cs
- PanelStyle.cs
- AppSettingsExpressionBuilder.cs