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 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
//------------------------------------------------------------------------------
// <copyright file="RegionIterator.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
// <owner current="true" primary="false">Microsoft</owner>
//------------------------------------------------------------------------------
#pragma warning disable 618 // ignore obsolete warning about XmlDataDocument
namespace System.Xml {
using System;
using System.Diagnostics;
using System.Text;
internal abstract class BaseRegionIterator : BaseTreeIterator {
internal BaseRegionIterator( DataSetMapper mapper ) : base( mapper ) {
}
}
// Iterates over non-attribute nodes
internal sealed class RegionIterator : BaseRegionIterator {
private XmlBoundElement rowElement;
private XmlNode currentNode;
internal RegionIterator( XmlBoundElement rowElement ) : base( ((XmlDataDocument)(rowElement.OwnerDocument)).Mapper ) {
Debug.Assert( rowElement != null && rowElement.Row != null );
this.rowElement = rowElement;
this.currentNode = rowElement;
}
internal override void Reset() {
currentNode = rowElement;
}
internal override XmlNode CurrentNode {
get {
return currentNode;
}
}
internal override bool Next() {
XmlNode nextNode;
ElementState oldState = rowElement.ElementState;
// We do not want to cause any foliation w/ this iterator or use this iterator once the region was defoliated
Debug.Assert( oldState != ElementState.None );
// Try to move to the first child
nextNode = currentNode.FirstChild;
// No children, try next sibling
if ( nextNode != null ) {
currentNode = nextNode;
// If we have been defoliated, we should have stayed that way
Debug.Assert( (oldState == ElementState.Defoliated) ? (rowElement.ElementState == ElementState.Defoliated) : true );
// Rollback foliation
rowElement.ElementState = oldState;
return true;
}
return NextRight();
}
internal override bool NextRight() {
// Make sure we do not get past the rowElement if we call NextRight on a just initialized iterator and rowElement has no children
if ( currentNode == rowElement ) {
currentNode = null;
return false;
}
ElementState oldState = rowElement.ElementState;
// We do not want to cause any foliation w/ this iterator or use this iterator once the region was defoliated
Debug.Assert( oldState != ElementState.None );
XmlNode nextNode = currentNode.NextSibling;
if ( nextNode != null ) {
currentNode = nextNode;
// If we have been defoliated, we should have stayed that way
Debug.Assert( (oldState == ElementState.Defoliated) ? (rowElement.ElementState == ElementState.Defoliated) : true );
// Rollback foliation
rowElement.ElementState = oldState;
return true;
}
// No next sibling, try the first sibling of from the parent chain
nextNode = currentNode;
while ( nextNode != rowElement && nextNode.NextSibling == null )
nextNode = nextNode.ParentNode;
if ( nextNode == rowElement ) {
currentNode = null;
// If we have been defoliated, we should have stayed that way
Debug.Assert( (oldState == ElementState.Defoliated) ? (rowElement.ElementState == ElementState.Defoliated) : true );
// Rollback foliation
rowElement.ElementState = oldState;
return false;
}
currentNode = nextNode.NextSibling;
Debug.Assert( currentNode != null );
// If we have been defoliated, we should have stayed that way
Debug.Assert( (oldState == ElementState.Defoliated) ? (rowElement.ElementState == ElementState.Defoliated) : true );
// Rollback foliation
rowElement.ElementState = oldState;
return true;
}
// Get the initial text value for the current node. You should be positioned on the node (element) for
// which to get the initial text value, not on the text node.
internal bool NextInitialTextLikeNodes( out String value ) {
Debug.Assert( this.CurrentNode != null );
Debug.Assert( this.CurrentNode.NodeType == XmlNodeType.Element );
#if DEBUG
// It's not OK to try to read the initial text value for sub-regions, because we do not know how to revert their initial state
if ( this.CurrentNode.NodeType == XmlNodeType.Element && mapper.GetTableSchemaForElement( (XmlElement)(this.CurrentNode) ) != null ) {
if ( this.CurrentNode != rowElement )
Debug.Assert( false );
}
#endif
ElementState oldState = rowElement.ElementState;
// We do not want to cause any foliation w/ this iterator or use this iterator once the region was defoliated
Debug.Assert( oldState != ElementState.None );
XmlNode n = this.CurrentNode.FirstChild;
value = GetInitialTextFromNodes( ref n );
if ( n == null ) {
// If we have been defoliated, we should have stayed that way
Debug.Assert( (oldState == ElementState.Defoliated) ? (rowElement.ElementState == ElementState.Defoliated) : true );
// Rollback eventual foliation
rowElement.ElementState = oldState;
return NextRight();
}
Debug.Assert( ! XmlDataDocument.IsTextLikeNode( n ) );
currentNode = n;
// If we have been defoliated, we should have stayed that way
Debug.Assert( (oldState == ElementState.Defoliated) ? (rowElement.ElementState == ElementState.Defoliated) : true );
// Rollback eventual foliation
rowElement.ElementState = oldState;
return true;
}
private static string GetInitialTextFromNodes( ref XmlNode n ) {
string value = null;
if ( n != null ) {
// don't consider whitespace
while ( n.NodeType == XmlNodeType.Whitespace ) {
n = n.NextSibling;
if ( n == null )
return String.Empty;
}
if ( XmlDataDocument.IsTextLikeNode( n ) && (n.NextSibling == null || ! XmlDataDocument.IsTextLikeNode( n.NextSibling )) ) {
// don't use string builder if only one text node exists
value = n.Value;
n = n.NextSibling;
}
else {
StringBuilder sb = new StringBuilder();
while ( n != null && XmlDataDocument.IsTextLikeNode( n ) ) {
// Ignore non-significant whitespace nodes
if ( n.NodeType != XmlNodeType.Whitespace )
sb.Append( n.Value );
n = n.NextSibling;
}
value = sb.ToString();
}
}
if ( value == null )
value = String.Empty;
return value;
}
}
}
|