//
// Authors:
// Atsushi Enomoto
//
// Copyright 2007 Novell (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if !MOONLIGHT
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
using XPISystem.Xml.Linq.XProcessingInstruction;
namespace System.Xml.Linq{
internal class XNodeNavigator : XPathNavigator
{
static readonly XAttribute attr_ns_xml = new XAttribute (XNamespace.Xmlns.GetName ("xml"), XNamespace.Xml.NamespaceName);
XNode node;
XAttribute attr;
XmlNameTable name_table;
public XNodeNavigator (XNode node, XmlNameTable nameTable)
{
this.node = node;
this.name_table = nameTable;
}
public XNodeNavigator (XNodeNavigator other)
{
this.node = other.node;
this.attr = other.attr;
this.name_table = other.name_table;
}
public override string BaseURI {
get { return node.BaseUri ?? String.Empty; }
}
public override bool CanEdit {
get { return true; }
}
public override bool HasAttributes {
get {
XElement el = node as XElement;
return el != null && el.HasAttributes;
}
}
public override bool HasChildren {
get {
XContainer c = node as XContainer;
return c != null && c.FirstNode != null;
}
}
public override bool IsEmptyElement {
get {
XElement el = node as XElement;
return el != null && el.IsEmpty;
}
}
public override string LocalName {
get {
switch (NodeType) {
case XPathNodeType.Namespace:
return attr.Name.Namespace == XNamespace.None ? String.Empty : attr.Name.LocalName;
case XPathNodeType.Attribute:
return attr.Name.LocalName;
case XPathNodeType.Element:
return ((XElement) node).Name.LocalName;
case XPathNodeType.ProcessingInstruction:
return ((XPI) node).Target;
default:
return String.Empty;
}
}
}
public override string Name {
get {
XName name = null;
switch (NodeType) {
case XPathNodeType.Attribute:
name = attr.Name;
break;
case XPathNodeType.Element:
name = ((XElement) node).Name;
break;
default:
return LocalName;
}
if (name.Namespace == XNamespace.None)
return name.LocalName;
XElement el = (node as XElement) ?? node.Parent;
if (el == null)
return name.LocalName;
string prefix = el.GetPrefixOfNamespace (name.Namespace);
return prefix.Length > 0 ? String.Concat (prefix, ":", name.LocalName) : name.LocalName;
}
}
public override string NamespaceURI {
get {
switch (NodeType) {
case XPathNodeType.Namespace:
return attr.Value;
case XPathNodeType.Attribute:
return attr.Name.NamespaceName;
case XPathNodeType.Element:
return ((XElement) node).Name.NamespaceName;
default:
return String.Empty;
}
}
}
public override XmlNameTable NameTable {
get { return name_table; }
}
public override XPathNodeType NodeType {
get {
if (attr != null)
return attr.IsNamespaceDeclaration ?
XPathNodeType.Namespace :
XPathNodeType.Attribute;
switch (node.NodeType) {
case XmlNodeType.Element:
return XPathNodeType.Element;
case XmlNodeType.Document:
return XPathNodeType.Root;
case XmlNodeType.Comment:
return XPathNodeType.Comment;
case XmlNodeType.ProcessingInstruction:
return XPathNodeType.ProcessingInstruction;
default:
return XPathNodeType.Text;
}
}
}
public override string Prefix {
get {
XName name = null;
switch (NodeType) {
case XPathNodeType.Attribute:
name = attr.Name;
break;
case XPathNodeType.Element:
name = ((XElement) node).Name;
break;
default:
return LocalName;
}
if (name.Namespace == XNamespace.None)
return String.Empty;
XElement el = (node as XElement) ?? node.Parent;
if (el == null)
return String.Empty;
return el.GetPrefixOfNamespace (name.Namespace);
}
}
public override IXmlSchemaInfo SchemaInfo {
get { return null; }
}
public override object UnderlyingObject {
get { return attr != null ? (object) attr : node; }
}
public override string Value {
get {
if (attr != null)
return attr.Value;
else
switch (NodeType) {
case XPathNodeType.Comment:
return ((XComment) node).Value;
case XPathNodeType.ProcessingInstruction:
return ((XPI) node).Data;
case XPathNodeType.Text:
return ((XText) node).Value;
case XPathNodeType.Element:
case XPathNodeType.Root:
return GetInnerText ((XContainer) node);
}
return String.Empty;
}
}
string GetInnerText (XContainer node)
{
StringBuilder sb = null;
foreach (XNode n in node.Nodes ())
GetInnerText (n, ref sb);
return sb != null ? sb.ToString () : String.Empty;
}
void GetInnerText (XNode n, ref StringBuilder sb)
{
switch (n.NodeType) {
case XmlNodeType.Element:
foreach (XNode c in ((XElement) n).Nodes ())
GetInnerText (c, ref sb);
break;
case XmlNodeType.Text:
case XmlNodeType.CDATA:
if (sb == null)
sb = new StringBuilder ();
sb.Append (((XText) n).Value);
break;
}
}
public override XPathNavigator Clone ()
{
return new XNodeNavigator (this);
}
public override bool IsSamePosition (XPathNavigator other)
{
XNodeNavigator nav = other as XNodeNavigator;
if (nav == null || nav.node.Owner != node.Owner)
return false;
return node == nav.node && attr == nav.attr;
}
public override bool MoveTo (XPathNavigator other)
{
XNodeNavigator nav = other as XNodeNavigator;
if (nav == null || nav.node.Owner != node.Owner)
return false;
node = nav.node;
attr = nav.attr;
return true;
}
public override bool MoveToFirstAttribute ()
{
XElement el = node as XElement;
if (el == null || !el.HasAttributes)
return false;
foreach (XAttribute a in el.Attributes ())
if (!a.IsNamespaceDeclaration) {
attr = a;
return true;
}
return false;
}
public override bool MoveToFirstChild ()
{
XContainer c = node as XContainer;
if (c == null || c.FirstNode == null)
return false;
node = c.FirstNode;
attr = null;
return true;
}
public override bool MoveToFirstNamespace (XPathNamespaceScope scope)
{
for (XElement el = node as XElement; el != null; el = el.Parent) {
foreach (XAttribute a in el.Attributes ())
if (a.IsNamespaceDeclaration) {
attr = a;
return true;
}
if (scope == XPathNamespaceScope.Local)
return false;
}
if (scope != XPathNamespaceScope.All)
return false;
attr = attr_ns_xml;
return true;
}
public override bool MoveToId (string id)
{
throw new NotSupportedException ("This XPathNavigator does not support IDs");
}
public override bool MoveToNext ()
{
if (node.NextNode == null)
return false;
node = node.NextNode;
attr = null;
return true;
}
public override bool MoveToNextAttribute ()
{
if (attr == null)
return false;
if (attr.NextAttribute == null)
return false;
for (XAttribute a = attr.NextAttribute; a != null; a = a.NextAttribute)
if (!a.IsNamespaceDeclaration) {
attr = a;
return true;
}
return false;
}
public override bool MoveToNextNamespace (XPathNamespaceScope scope)
{
if (attr == null)
return false;
for (XAttribute a = attr.NextAttribute; a != null; a = a.NextAttribute)
if (a.IsNamespaceDeclaration) {
attr = a;
return true;
}
if (scope == XPathNamespaceScope.Local)
return false;
for (XElement el = ((XElement) attr.Parent).Parent; el != null; el = el.Parent) {
foreach (XAttribute a in el.Attributes ())
if (a.IsNamespaceDeclaration) {
attr = a;
return true;
}
}
if (scope != XPathNamespaceScope.All)
return false;
attr = attr_ns_xml;
return true;
}
public override bool MoveToParent ()
{
if (attr != null) {
attr = null;
return true;
}
if (node.Parent == null)
return false;
node = node.Parent;
return true;
}
public override bool MoveToPrevious ()
{
if (node.PreviousNode == null)
return false;
node = node.PreviousNode;
attr = null;
return true;
}
public override void MoveToRoot ()
{
node = node.Owner;
attr = null;
}
}
}
#endif
|