1 //------------------------------------------------------------------------------
2 // <copyright file="XPathNodePointer.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
8 #pragma warning disable 618 // ignore obsolete warning about XmlDataDocument
12 using System.Diagnostics;
13 using System.Xml.XPath;
15 internal sealed class XPathNodePointer : IXmlDataVirtualNode {
16 private WeakReference _owner; // Owner of this pointer (an DataDocumentXPathNavigator). When the associated DataDocumentXPathNavigator (the owner) goes away, this XPathNodePointer can go away as well.
17 private XmlDataDocument _doc;
18 private XmlNode _node;
19 private DataColumn _column;
20 private bool _fOnValue;
21 internal XmlBoundElement _parentOfNS;
22 internal static int[] xmlNodeType_To_XpathNodeType_Map;
23 internal static string s_strReservedXmlns = "http://www.w3.org/2000/xmlns/";
24 internal static string s_strReservedXml = "http://www.w3.org/XML/1998/namespace";
25 internal static string s_strXmlNS = "xmlns";
26 private bool _bNeedFoliate;
28 static XPathNodePointer(){
31 Array enumValues = Enum.GetValues(typeof(XmlNodeType));
32 for ( int i = 0; i < enumValues.Length; i++) {
33 tempVal = (int)enumValues.GetValue(i);
37 Debug.Assert( max == (int) XmlNodeType.XmlDeclaration );
39 xmlNodeType_To_XpathNodeType_Map = new int[20];
40 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.None)] = -1;
41 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Element)] = (int)XPathNodeType.Element;
42 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Attribute)] = (int)XPathNodeType.Attribute;
43 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Text)] = (int)XPathNodeType.Text;
44 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.CDATA)] = (int)XPathNodeType.Text;
45 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.EntityReference)] = -1;
46 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Entity)] = -1;
47 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.ProcessingInstruction)] = (int)XPathNodeType.ProcessingInstruction;
48 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Comment)] = (int)XPathNodeType.Comment;
49 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Document)] = (int)XPathNodeType.Root;
50 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.DocumentType)] = -1;
51 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.DocumentFragment)] = (int)XPathNodeType.Root;
52 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Notation)] = -1;
53 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Whitespace)] = (int)XPathNodeType.Whitespace;
54 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.SignificantWhitespace)] = (int)XPathNodeType.SignificantWhitespace;
55 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.EndElement)] = -1;
56 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.EndEntity)] = -1;
57 xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.XmlDeclaration)] = -1;
58 // xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.All)] = -1;
61 private XPathNodeType DecideXPNodeTypeForTextNodes( XmlNode node ) {
62 //the function can only be called on text like nodes.
63 Debug.Assert( XmlDataDocument.IsTextNode( node.NodeType ) );
64 XPathNodeType xnt = XPathNodeType.Whitespace;
65 while( node != null ) {
66 switch( node.NodeType ) {
67 case XmlNodeType.Whitespace :
69 case XmlNodeType.SignificantWhitespace :
70 xnt = XPathNodeType.SignificantWhitespace;
72 case XmlNodeType.Text :
73 case XmlNodeType.CDATA :
74 return XPathNodeType.Text;
78 node = this._doc.SafeNextSibling(node);
83 private XPathNodeType ConvertNodeType( XmlNode node ) {
85 if ( XmlDataDocument.IsTextNode( node.NodeType ) )
86 return DecideXPNodeTypeForTextNodes( node );
87 xnt = xmlNodeType_To_XpathNodeType_Map[(int)(node.NodeType)];
88 if ( xnt == (int) XPathNodeType.Attribute ) {
89 if ( node.NamespaceURI == s_strReservedXmlns )
90 return XPathNodeType.Namespace;
92 return XPathNodeType.Attribute;
94 Debug.Assert( xnt != -1 );
95 return (XPathNodeType)xnt;
98 private bool IsNamespaceNode( XmlNodeType nt, string ns ) {
99 if ( nt == XmlNodeType.Attribute && ns == s_strReservedXmlns )
104 //when the constructor is called, the node has to be a valid XPath node at the valid location ( for example, the first
105 //text/WS/SWS/CData nodes of a series continuous text-like nodes.
106 internal XPathNodePointer( DataDocumentXPathNavigator owner, XmlDataDocument doc, XmlNode node )
107 : this ( owner, doc, node, null, false, null ){
110 internal XPathNodePointer( DataDocumentXPathNavigator owner, XPathNodePointer pointer )
111 : this ( owner, pointer._doc, pointer._node, pointer._column, pointer._fOnValue, pointer._parentOfNS ) {
114 private XPathNodePointer( DataDocumentXPathNavigator owner, XmlDataDocument doc, XmlNode node, DataColumn c, bool bOnValue, XmlBoundElement parentOfNS ) {
115 Debug.Assert( owner != null );
116 this._owner = new WeakReference( owner );
120 this._fOnValue = bOnValue;
121 this._parentOfNS = parentOfNS;
122 // Add this pointer to the document so it will be updated each time region changes it's foliation state.
123 this._doc.AddPointer( (IXmlDataVirtualNode)this );
124 _bNeedFoliate = false;
128 internal XPathNodePointer Clone( DataDocumentXPathNavigator owner ){
129 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Clone");
131 return new XPathNodePointer( owner, this ) ;
134 internal bool IsEmptyElement {
136 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsEmptyElement");
138 if (_node != null && _column == null) {
139 if (_node.NodeType == XmlNodeType.Element) {
140 return((XmlElement)_node).IsEmpty;
147 internal XPathNodeType NodeType {
149 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:NodeType");
152 if (this._node == null) {
153 return XPathNodeType.All;
155 else if (this._column == null) {
156 return ConvertNodeType(this._node);
158 else if (this._fOnValue) {
159 return XPathNodeType.Text;
161 else if (this._column.ColumnMapping == MappingType.Attribute) {
162 if ( this._column.Namespace == s_strReservedXmlns )
163 return XPathNodeType.Namespace;
165 return XPathNodeType.Attribute;
168 return XPathNodeType.Element;
172 //[....]: From CodeReview: Perf: We should have another array similar w/
173 // xmlNodeType_To_XpathNodeType_Map that will return String.Empty for everything but the element and
175 internal string LocalName {
177 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:LocalName");
180 if (this._node == null) {
183 else if (this._column == null) {
184 XmlNodeType nt = this._node.NodeType;
185 if ( IsNamespaceNode( nt, this._node.NamespaceURI ) && this._node.LocalName == s_strXmlNS )
187 if ( nt == XmlNodeType.Element || nt == XmlNodeType.Attribute || nt == XmlNodeType.ProcessingInstruction )
188 return _node.LocalName;
191 else if (this._fOnValue) {
194 else //when column is not null
195 return _doc.NameTable.Add(_column.EncodedColumnName);
199 //note that, we've have lost the prefix in this senario ( defoliation will toss prefix away. )
200 internal string Name {
202 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Name");
205 if (this._node == null) {
208 else if (this._column == null) {
209 XmlNodeType nt = this._node.NodeType;
210 if ( IsNamespaceNode( nt, this._node.NamespaceURI ) ) {
211 if ( this._node.LocalName == s_strXmlNS )
214 return this._node.LocalName;
216 if ( nt == XmlNodeType.Element || nt == XmlNodeType.Attribute || nt == XmlNodeType.ProcessingInstruction )
220 else if (this._fOnValue) {
223 else { //when column is not null
224 //we've lost prefix in this senario.
225 return _doc.NameTable.Add(_column.EncodedColumnName);
230 internal string NamespaceURI {
232 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:NamespaceURI");
235 if (this._node == null) {
238 else if (this._column == null) {
239 XPathNodeType xnt = ConvertNodeType( this._node );
240 if ( xnt == XPathNodeType.Element || xnt == XPathNodeType.Root || xnt == XPathNodeType.Attribute )
241 return _node.NamespaceURI;
244 else if (this._fOnValue) {
247 else { //When column is not null
248 if ( _column.Namespace == s_strReservedXmlns )
249 //namespace nodes has empty string as namespaceURI
251 return _doc.NameTable.Add(_column.Namespace);
257 internal string Prefix {
259 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Prefix");
262 if (this._node == null) {
265 else if (this._column == null) {
266 if ( IsNamespaceNode( this._node.NodeType, this._node.NamespaceURI ) )
274 internal string Value {
276 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Value");
279 if (this._node == null)
281 else if (this._column == null) {
282 string strRet = this._node.Value;
283 if ( XmlDataDocument.IsTextNode( this._node.NodeType ) ) {
284 //concatenate adjacent textlike nodes
285 XmlNode parent = this._node.ParentNode;
286 if ( parent == null )
288 XmlNode n = _doc.SafeNextSibling(this._node);
289 while ( n != null && XmlDataDocument.IsTextNode( n.NodeType ) ) {
291 n = _doc.SafeNextSibling(n);
296 else if (this._column.ColumnMapping == MappingType.Attribute || this._fOnValue) {
297 DataRow row = this.Row;
298 DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
299 object value = row[ this._column, rowVersion ];
300 if ( ! Convert.IsDBNull( value ) )
301 return this._column.ConvertObjectToXml( value );
310 internal string InnerText {
312 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:InnerText");
315 if (this._node == null) {
318 else if (this._column == null) {
320 if ( this._node.NodeType == XmlNodeType.Document ) {
321 //document node's region should always be uncompressed
322 XmlElement rootElem = ((XmlDocument)this._node).DocumentElement;
323 if ( rootElem != null )
324 return rootElem.InnerText;
328 return this._node.InnerText;
331 DataRow row = this.Row;
332 DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
333 object value = row[ this._column, rowVersion ];
334 if ( ! Convert.IsDBNull( value ) )
335 return this._column.ConvertObjectToXml( value );
341 internal String BaseURI {
343 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:BaseURI");
345 if ( this._node != null )
346 return this._node.BaseURI;
351 internal String XmlLang {
353 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:XmlLang");
355 XmlNode curNode = this._node;
356 XmlBoundElement curBoundElem = null;
357 object colVal = null;
358 while ( curNode != null ) {
361 curBoundElem = curNode as XmlBoundElement;
362 if ( curBoundElem != null ) {
363 //this._doc.Foliate( curBoundElem, ElementState.WeakFoliation );
364 if ( curBoundElem.ElementState == ElementState.Defoliated ) {
365 //if not foliated, going through the columns to get the xml:lang
366 DataRow row = curBoundElem.Row;
367 foreach( DataColumn col in row.Table.Columns ) {
368 if ( col.Prefix == "xml" && col.EncodedColumnName == "lang" ) {
370 if ( colVal == DBNull.Value )
371 break; //goto its ancesstors
372 return (String) colVal;
377 //if folicated, get the attribute directly
378 if ( curBoundElem.HasAttribute( "xml:lang" ) )
379 return curBoundElem.GetAttribute( "xml:lang" );
382 if ( curNode.NodeType == XmlNodeType.Attribute )
383 curNode = ((XmlAttribute)curNode).OwnerElement;
385 curNode = curNode.ParentNode;
391 private XmlBoundElement GetRowElement() {
392 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetRowElement()");
395 XmlBoundElement rowElem;
396 if ( this._column != null ) {
397 rowElem = this._node as XmlBoundElement;
398 Debug.Assert( rowElem != null );
399 Debug.Assert( rowElem.Row != null );
403 _doc.Mapper.GetRegion( this._node, out rowElem );
408 private DataRow Row {
410 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Row");
412 XmlBoundElement rowElem = GetRowElement();
413 if ( rowElem == null )
416 Debug.Assert( rowElem.Row != null );
421 internal bool MoveTo( XPathNodePointer pointer ) {
422 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveTo(pointer)");
424 if ( this._doc != pointer._doc )
427 XmlDataDocument docOld = this._doc;
428 XmlDataDocument docNew = pointer._doc;
429 if ( docNew != docOld ) {
430 this._doc.RemovePointer( this );
431 this._doc = pointer._doc;
432 this._doc.AddPointer( this );
435 this._node = pointer._node;
436 this._column = pointer._column;
437 this._fOnValue = pointer._fOnValue;
438 this._bNeedFoliate = pointer._bNeedFoliate;
443 private void MoveTo( XmlNode node ) {
444 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveTo(node)");
446 // Should not move outside of this document
447 Debug.Assert( node == this._doc || node.OwnerDocument == this._doc );
450 this._fOnValue = false;
454 private void MoveTo( XmlNode node, DataColumn column, bool _fOnValue ) {
455 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveTo(node, column, fOnValue)");
457 // Should not move outside of this document
458 Debug.Assert( node == this._doc || node.OwnerDocument == this._doc );
460 this._column = column;
461 this._fOnValue = _fOnValue;
465 private bool IsFoliated( XmlNode node ) {
466 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsFoliated(node)");
468 if (node != null && node is XmlBoundElement)
469 return((XmlBoundElement)node).IsFoliated;
473 private int ColumnCount( DataRow row, bool fAttribute ) {
474 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:ColumnCount(row,fAttribute)");
477 while ((c = NextColumn( row, c, fAttribute )) != null) {
478 if ( c.Namespace != s_strReservedXmlns )
484 internal int AttributeCount {
486 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:AttributeCount");
490 if (_column == null && _node.NodeType == XmlNodeType.Element) {
491 if (!IsFoliated( _node ))
492 return ColumnCount( Row, true );
495 foreach ( XmlAttribute attr in _node.Attributes ) {
496 if ( attr.NamespaceURI != s_strReservedXmlns )
507 internal DataColumn NextColumn( DataRow row, DataColumn col, bool fAttribute ) {
508 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:NextColumn(row,col,fAttribute)");
509 if (row.RowState == DataRowState.Deleted)
512 DataTable table = row.Table;
513 DataColumnCollection columns = table.Columns;
514 int iColumn = (col != null) ? col.Ordinal + 1 : 0;
515 int cColumns = columns.Count;
516 DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
518 for (; iColumn < cColumns; iColumn++) {
519 DataColumn c = columns[iColumn];
520 if (!_doc.IsNotMapped( c ) && (c.ColumnMapping == MappingType.Attribute) == fAttribute && ! Convert.IsDBNull( row[c, rowVersion] ) )
527 internal DataColumn PreviousColumn( DataRow row, DataColumn col, bool fAttribute ) {
528 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:PreviousColumn(row,col,fAttribute)");
529 if (row.RowState == DataRowState.Deleted)
532 DataTable table = row.Table;
533 DataColumnCollection columns = table.Columns;
534 int iColumn = (col != null) ? col.Ordinal - 1 : columns.Count - 1;
535 int cColumns = columns.Count;
536 DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
538 for (; iColumn >= 0; iColumn--) {
539 DataColumn c = columns[iColumn];
540 if (!_doc.IsNotMapped( c ) && (c.ColumnMapping == MappingType.Attribute) == fAttribute && !Convert.IsDBNull( row[c, rowVersion] ) )
547 internal bool MoveToAttribute( string localName, string namespaceURI ) {
548 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToAttribute(localName, namespaceURI)");
551 if ( namespaceURI == s_strReservedXmlns )
554 //_column.ColumnMapping checkin below is not really needed since the pointer should be pointing at the node before this
555 // function should even be called ( there is always a call MoveToOwnerElement() before MoveToAttribute(..)
556 if ((_column == null || _column.ColumnMapping == MappingType.Attribute) && _node.NodeType == XmlNodeType.Element) {
557 if (!IsFoliated( _node )) {
559 while ((c = NextColumn( Row, c, true )) != null) {
560 if (c.EncodedColumnName == localName && c.Namespace == namespaceURI) {
561 MoveTo( _node, c, false );
567 Debug.Assert( _node.Attributes != null );
568 XmlNode n = _node.Attributes.GetNamedItem(localName, namespaceURI);
570 MoveTo( n, null, false );
579 internal bool MoveToNextAttribute( bool bFirst ) {
580 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextAttribute(bFirst)");
585 if ( bFirst && ( _column != null || _node.NodeType != XmlNodeType.Element ) )
588 if ( _column != null && _column.ColumnMapping != MappingType.Attribute )
590 if ( _column == null && _node.NodeType != XmlNodeType.Attribute )
593 if ( !IsFoliated( _node ) ) {
594 DataColumn c = _column;
595 while ( ( c = NextColumn( Row, c, true ) ) != null ) {
596 if ( c.Namespace != s_strReservedXmlns ) {
597 MoveTo( _node, c, false );
605 XmlAttributeCollection attrs = _node.Attributes;
606 foreach ( XmlAttribute attr in attrs ) {
607 if ( attr.NamespaceURI != s_strReservedXmlns ) {
608 MoveTo( attr, null, false );
614 XmlAttributeCollection attrs = ((XmlAttribute)_node).OwnerElement.Attributes;
616 foreach ( XmlAttribute attr in attrs ) {
617 if ( bFound && attr.NamespaceURI != s_strReservedXmlns ) {
618 MoveTo( attr, null, false );
630 private bool IsValidChild( XmlNode parent, XmlNode child ) {
631 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsValidChild(parent,child)");
632 int xntChildInt = xmlNodeType_To_XpathNodeType_Map[(int)(child.NodeType)];
633 if ( xntChildInt == -1 )
635 int xntInt = xmlNodeType_To_XpathNodeType_Map[(int)(parent.NodeType)];
636 Debug.Assert( xntInt != -1 );
638 case (int)XPathNodeType.Root:
639 return ( xntChildInt == (int)XPathNodeType.Element ||
640 xntChildInt == (int)XPathNodeType.Comment ||
641 xntChildInt == (int)XPathNodeType.ProcessingInstruction );
642 case (int)XPathNodeType.Element:
643 return ( xntChildInt == (int)XPathNodeType.Element ||
644 xntChildInt == (int)XPathNodeType.Text ||
645 xntChildInt == (int)XPathNodeType.Comment ||
646 xntChildInt == (int)XPathNodeType.Whitespace ||
647 xntChildInt == (int)XPathNodeType.SignificantWhitespace ||
648 xntChildInt == (int)XPathNodeType.ProcessingInstruction );
654 private bool IsValidChild( XmlNode parent, DataColumn c ) {
655 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsValidChild(parent,c)");
656 int xntInt = xmlNodeType_To_XpathNodeType_Map[(int)(parent.NodeType)];
657 Debug.Assert( xntInt != -1 );
659 case (int)XPathNodeType.Root:
660 return c.ColumnMapping == MappingType.Element;
661 case (int)XPathNodeType.Element:
662 return ( c.ColumnMapping == MappingType.Element || c.ColumnMapping == MappingType.SimpleContent );
668 internal bool MoveToNextSibling() {
669 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextSibling()");
673 if ( _column != null ) {
675 // _fOnValue could be true only when the column is mapped as simplecontent or element
676 Debug.Assert( _column.ColumnMapping != MappingType.Attribute && _column.ColumnMapping != MappingType.Hidden );
679 DataRow curRow = Row;
680 DataColumn c = NextColumn( curRow, _column, false );
681 while ( c != null ) {
682 if ( IsValidChild( _node, c ) ) {
683 MoveTo( this._node, c, _doc.IsTextOnly(c));
686 c = NextColumn( curRow, c, false );
688 XmlNode n = _doc.SafeFirstChild( _node );
696 XmlNode parent = _node.ParentNode;
697 if ( parent == null )
699 bool bTextLike = XmlDataDocument.IsTextNode( _node.NodeType );
702 n = _doc.SafeNextSibling(n);
703 } while ( n != null && bTextLike && XmlDataDocument.IsTextNode( n.NodeType ));
704 } while ( n != null && !IsValidChild(parent, n) );
714 internal bool MoveToPreviousSibling() {
715 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToPreviousSibling()");
719 if (_column != null) {
722 DataRow curRow = Row;
723 DataColumn c = PreviousColumn( curRow, _column, false );
724 while ( c != null ) {
725 if ( IsValidChild(_node,c)) {
726 MoveTo( _node, c, _doc.IsTextOnly(c) );
729 c = PreviousColumn( curRow, c , false );
734 XmlNode parent = _node.ParentNode;
735 if ( parent == null )
737 bool bTextLike = XmlDataDocument.IsTextNode( _node.NodeType );
740 n = _doc.SafePreviousSibling( n );
741 } while ( n != null && bTextLike && XmlDataDocument.IsTextNode( n.NodeType ) );
742 } while ( n != null && !IsValidChild(parent, n) );
747 if (!IsFoliated( parent ) && (parent is XmlBoundElement)) {
748 DataRow row = ((XmlBoundElement)parent).Row;
750 DataColumn c = PreviousColumn( row, null, false );
752 MoveTo( parent, c, _doc.IsTextOnly(c) );
762 internal bool MoveToFirst() {
763 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToFirst()");
767 DataRow curRow = null;
768 XmlNode parent = null;
769 if (_column != null) {
774 parent = _node.ParentNode;
775 if ( parent == null )
777 if ( !IsFoliated( parent ) && (parent is XmlBoundElement) )
778 curRow = ((XmlBoundElement)parent).Row;
780 //first check with the columns in the row
781 if ( curRow != null ) {
782 DataColumn c = NextColumn( curRow, null, false );
783 while ( c != null ) {
784 if ( IsValidChild( _node, c ) ) {
785 MoveTo( _node, c, _doc.IsTextOnly( c ) );
788 c = NextColumn( curRow, c, false );
791 //didn't find a valid column or maybe already Foliated, go through its children nodes
792 XmlNode n = _doc.SafeFirstChild( parent );
793 while ( n != null ) {
794 if ( IsValidChild( parent, n ) ) {
798 n = _doc.SafeNextSibling( n );
804 internal bool HasChildren {
806 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:HasChildren");
812 if (_column != null) {
813 if ( _column.ColumnMapping == MappingType.Attribute || _column.ColumnMapping == MappingType.Hidden )
817 if (!IsFoliated( _node )) {
818 // find virtual column elements first
819 DataRow curRow = Row;
820 DataColumn c = NextColumn( curRow, null, false );
821 while ( c != null ) {
822 if ( IsValidChild( _node, c) )
824 c = NextColumn( curRow, c, false );
828 XmlNode n = _doc.SafeFirstChild( _node );
829 while ( n != null ) {
830 if ( IsValidChild( _node, n ) )
832 n = _doc.SafeNextSibling( n );
839 internal bool MoveToFirstChild() {
840 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToFirstChild()");
846 if (_column != null) {
847 if ( _column.ColumnMapping == MappingType.Attribute || _column.ColumnMapping == MappingType.Hidden )
849 if (_fOnValue) //text node has no children to move to
854 if (!IsFoliated( _node )) {
855 // find virtual column elements first
856 DataRow curRow = Row;
857 DataColumn c = NextColumn( curRow, null, false );
858 while ( c != null ) {
859 if ( IsValidChild( _node, c) ) {
860 MoveTo( _node, c, _doc.IsTextOnly(c) );
863 c = NextColumn( curRow, c, false );
867 XmlNode n = _doc.SafeFirstChild( _node );
868 while ( n != null ) {
869 if ( IsValidChild( _node, n ) ) {
873 n = _doc.SafeNextSibling( n );
879 //this version of MoveToParent will consider Attribute type position and move to its owner element
881 internal bool MoveToParent() {
882 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToParent()");
885 if ( NodeType == XPathNodeType.Namespace ) {
886 Debug.Assert( _parentOfNS != null );
887 MoveTo( _parentOfNS );
891 if (_column != null) {
892 if (_fOnValue && !_doc.IsTextOnly(_column)) {
893 MoveTo( _node, _column, false );
896 MoveTo( _node, null, false );
901 if ( _node.NodeType == XmlNodeType.Attribute )
902 n = ((XmlAttribute)_node).OwnerElement;
904 n = _node.ParentNode;
914 private XmlNode GetParent( XmlNode node ) {
915 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetParent(node)");
916 XPathNodeType xnt = ConvertNodeType( node );
917 if ( xnt == XPathNodeType.Namespace ) {
918 Debug.Assert( _parentOfNS != null );
921 if ( xnt == XPathNodeType.Attribute )
922 return ((XmlAttribute)node).OwnerElement;
923 return node.ParentNode;
926 internal void MoveToRoot() {
927 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToRoot()");
928 XmlNode node = this._node;
929 XmlNode parent = this._node;
930 while ( parent != null ) {
932 parent = GetParent(parent);
936 this._fOnValue = false;
940 internal bool IsSamePosition( XPathNodePointer pointer ) {
941 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsSamePosition(pointer)");
943 pointer.RealFoliate();
945 pointer.AssertValid();
946 if (_column == null && pointer._column == null)
947 return ( pointer._node == this._node && pointer._parentOfNS == this._parentOfNS );
949 return ( pointer._doc == this._doc
950 && pointer._node == this._node
951 && pointer._column == this._column
952 && pointer._fOnValue == this._fOnValue
953 && pointer._parentOfNS == this._parentOfNS );
956 private XmlNodeOrder CompareNamespacePosition( XPathNodePointer other ) {
957 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:CompareNamespacePostion(other)");
958 XPathNodePointer xp1 = this.Clone((DataDocumentXPathNavigator)(this._owner.Target));
959 XPathNodePointer xp2 = other.Clone((DataDocumentXPathNavigator)(other._owner.Target));
960 while ( xp1.MoveToNextNamespace(XPathNamespaceScope.All) ) {
961 if ( xp1.IsSamePosition( other ) )
962 return XmlNodeOrder.Before;
964 return XmlNodeOrder.After;
967 private static XmlNode GetRoot( XmlNode node, ref int depth ) {
968 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetRoot(node, depth)");
970 XmlNode curNode = node;
971 XmlNode parent = ( ( curNode.NodeType == XmlNodeType.Attribute ) ? ( ((XmlAttribute)curNode).OwnerElement ) : ( curNode.ParentNode ) );
972 for ( ; parent != null; depth++ ) {
974 parent = curNode.ParentNode; // no need to check for attribute since navigator can't be built on its children or navigate to its children
979 internal XmlNodeOrder ComparePosition( XPathNodePointer other ) {
980 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:ComparePosition(other)");
983 Debug.Assert( other != null );
984 if ( IsSamePosition( other ) )
985 return XmlNodeOrder.Same;
986 XmlNode curNode1 = null, curNode2 = null;
987 //deal with namespace node first
988 if ( this.NodeType == XPathNodeType.Namespace && other.NodeType == XPathNodeType.Namespace ) {
989 if ( this._parentOfNS == other._parentOfNS )
990 return this.CompareNamespacePosition( other );
991 //if not from the same parent
992 curNode1 = this._parentOfNS;
993 curNode2 = other._parentOfNS;
995 else if ( this.NodeType == XPathNodeType.Namespace ) {
996 Debug.Assert( other.NodeType != XPathNodeType.Namespace );
997 if ( this._parentOfNS == other._node ) {
998 //from the same region, NS nodes come before all other nodes
999 if ( other._column == null )
1000 return XmlNodeOrder.After;
1002 return XmlNodeOrder.Before;
1004 //if not from the same region
1005 curNode1 = this._parentOfNS;
1006 curNode2 = other._node;
1008 else if ( other.NodeType == XPathNodeType.Namespace ) {
1009 Debug.Assert( this.NodeType != XPathNodeType.Namespace );
1010 if ( this._node == other._parentOfNS ) {
1011 //from the same region
1012 if ( this._column == null )
1013 return XmlNodeOrder.Before;
1015 return XmlNodeOrder.After;
1017 //if not from the same region
1018 curNode1 = this._node;
1019 curNode2 = other._parentOfNS;
1022 if ( this._node == other._node ) {
1023 //compare within the same region
1024 if ( this._column == other._column ) {
1025 //one is the children of the other
1026 Debug.Assert( this._fOnValue != other._fOnValue );
1027 if ( this._fOnValue )
1028 return XmlNodeOrder.After;
1030 return XmlNodeOrder.Before;
1033 Debug.Assert( this.Row == other.Row ); //in the same row
1034 if ( this._column == null )
1035 return XmlNodeOrder.Before;
1036 else if ( other._column == null )
1037 return XmlNodeOrder.After;
1038 else if ( this._column.Ordinal < other._column.Ordinal )
1039 return XmlNodeOrder.Before;
1041 return XmlNodeOrder.After;
1044 curNode1 = this._node;
1045 curNode2 = other._node;
1049 Debug.Assert( curNode1 != null );
1050 Debug.Assert( curNode2 != null );
1052 if (curNode1 == null || curNode2 == null) {
1053 return XmlNodeOrder.Unknown;
1057 int depth1 = -1, depth2 = -1;
1058 XmlNode root1 = XPathNodePointer.GetRoot( curNode1, ref depth1 );
1059 XmlNode root2 = XPathNodePointer.GetRoot( curNode2, ref depth2 );
1060 if ( root1 != root2 )
1061 return XmlNodeOrder.Unknown;
1063 if ( depth1 > depth2 ) {
1064 while ( curNode1 != null && depth1 > depth2 ) {
1065 curNode1 = ( ( curNode1.NodeType == XmlNodeType.Attribute ) ? ( ((XmlAttribute)curNode1).OwnerElement ) : ( curNode1.ParentNode ) );
1068 if ( curNode1 == curNode2 )
1069 return XmlNodeOrder.After;
1071 else if ( depth2 > depth1 ) {
1072 while ( curNode2 != null && depth2 > depth1 ) {
1073 curNode2 = ( ( curNode2.NodeType == XmlNodeType.Attribute ) ? ( ((XmlAttribute)curNode2).OwnerElement ) : ( curNode2.ParentNode ) );
1076 if ( curNode1 == curNode2 )
1077 return XmlNodeOrder.Before;
1080 XmlNode parent1 = GetParent(curNode1);
1081 XmlNode parent2 = GetParent(curNode2);
1082 XmlNode nextNode = null;
1083 while ( parent1 != null && parent2 != null ) {
1084 if ( parent1 == parent2 ) {
1085 while (curNode1 != null ) {
1086 nextNode = curNode1.NextSibling;
1087 if ( nextNode == curNode2 )
1088 return XmlNodeOrder.Before;
1089 curNode1 = nextNode;
1091 return XmlNodeOrder.After;
1095 parent1 = curNode1.ParentNode;
1096 parent2 = curNode2.ParentNode;
1099 //logically, we shouldn't reach here
1100 Debug.Assert( false );
1101 return XmlNodeOrder.Unknown;
1104 internal XmlNode Node {
1106 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Node");
1110 if ( this._node == null )
1113 XmlBoundElement rowElem = GetRowElement();
1114 if ( rowElem != null ) {
1115 //lock ( this._doc.pointers ) {
1116 bool wasFoliationEnabled = this._doc.IsFoliationEnabled;
1117 this._doc.IsFoliationEnabled = true;
1118 this._doc.Foliate( rowElem, ElementState.StrongFoliation );
1119 this._doc.IsFoliationEnabled = wasFoliationEnabled;
1128 bool IXmlDataVirtualNode.IsOnNode( XmlNode nodeToCheck ) {
1129 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsOnNode(nodeToCheck)");
1131 return nodeToCheck == this._node;
1134 bool IXmlDataVirtualNode.IsOnColumn( DataColumn col ) {
1135 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsOnColumn(col)");
1137 return col == this._column;
1140 void IXmlDataVirtualNode.OnFoliated( XmlNode foliatedNode ) {
1141 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:OnFoliated(foliatedNode)");
1142 // update the pointer if the element node has been foliated
1143 if (_node == foliatedNode) {
1144 // if already on this node, nothing to do!
1145 if (_column == null)
1147 _bNeedFoliate = true;
1151 private void RealFoliate() {
1152 if ( !_bNeedFoliate )
1154 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:RealFoliate()");
1155 _bNeedFoliate = false;
1157 Debug.Assert( this._column != null );
1161 if (_doc.IsTextOnly( _column ))
1162 n = _node.FirstChild;
1164 if (_column.ColumnMapping == MappingType.Attribute) {
1165 n = _node.Attributes.GetNamedItem( _column.EncodedColumnName, _column.Namespace );
1168 for (n = _node.FirstChild; n != null; n = n.NextSibling) {
1169 if (n.LocalName == _column.EncodedColumnName && n.NamespaceURI == _column.Namespace)
1174 if (n != null && _fOnValue)
1179 throw new InvalidOperationException(Res.GetString(Res.DataDom_Foliation));
1181 // Cannot use MoveTo( n ); b/c the initial state for MoveTo is invalid (region is foliated but this is not)
1183 this._column = null;
1184 this._fOnValue = false;
1186 _bNeedFoliate = false;
1190 //The function only helps to find out if there is a namespace declaration of given name is defined on the given node
1191 //It will not check the accestors of the given node.
1192 private string GetNamespace( XmlBoundElement be, string name ) {
1193 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetNamespace(be,name)");
1197 XmlAttribute attr = null;
1198 if ( be.IsFoliated ) {
1199 attr = be.GetAttributeNode ( name, s_strReservedXmlns );
1205 else { //defoliated so that we need to search through its column
1206 DataRow curRow = be.Row;
1207 if ( curRow == null )
1209 //going through its attribute columns
1210 DataColumn curCol = PreviousColumn( curRow, null, true );
1211 while ( curCol != null ) {
1212 if ( curCol.Namespace == s_strReservedXmlns ) {
1214 DataRowVersion rowVersion = ( curRow.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
1215 return curCol.ConvertObjectToXml( curRow[curCol,rowVersion] );
1217 curCol = PreviousColumn( curRow, curCol, true );
1223 internal string GetNamespace(string name) {
1224 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetNamespace(name)");
1225 //we are checking the namespace nodes backwards comparing its normal order in DOM tree
1226 if ( name == "xml" )
1227 return s_strReservedXml;
1228 if ( name == "xmlns" )
1229 return s_strReservedXmlns;
1230 if ( name != null && name.Length == 0 )
1233 XmlNode node = _node;
1234 XmlNodeType nt = node.NodeType;
1235 String retVal = null;
1236 while ( node != null ) {
1237 //first identify an element node in the ancestor + itself
1238 while ( node != null && ( ( nt = node.NodeType ) != XmlNodeType.Element ) ) {
1239 if ( nt == XmlNodeType.Attribute )
1240 node = ((XmlAttribute)node).OwnerElement;
1242 node = node.ParentNode;
1244 //found one -- inside if
1245 if ( node != null ) {
1246 //must be element node
1247 retVal = GetNamespace((XmlBoundElement)node, name);
1248 if ( retVal != null )
1250 //didn't find it, try the next parentnode
1251 node = node.ParentNode;
1254 //nothing happens, then return string.empty.
1255 return string.Empty;
1258 internal bool MoveToNamespace(string name) {
1259 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNamespace(name)");
1260 _parentOfNS = this._node as XmlBoundElement;
1261 //only need to check with _node, even if _column is not null and its mapping type is element, it can't have attributes
1262 if ( _parentOfNS == null )
1264 string attrName = name;
1265 if ( attrName == "xmlns" )
1266 attrName = "xmlns:xmlns";
1267 if ( attrName != null && attrName.Length == 0 )
1270 XmlNode node = this._node;
1271 XmlNodeType nt = node.NodeType;
1272 XmlAttribute attr = null;
1273 XmlBoundElement be = null;
1274 while ( node != null ) {
1275 //check current element node
1276 be = node as XmlBoundElement;
1278 if ( be.IsFoliated ) {
1279 attr = be.GetAttributeNode ( name, s_strReservedXmlns );
1280 if ( attr != null ) {
1285 else {//defoliated so that we need to search through its column
1286 DataRow curRow = be.Row;
1287 if ( curRow == null )
1289 //going through its attribute columns
1290 DataColumn curCol = PreviousColumn( curRow, null, true );
1291 while ( curCol != null ) {
1292 if ( curCol.Namespace == s_strReservedXmlns && curCol.ColumnName == name ) {
1293 MoveTo( be, curCol, false );
1296 curCol = PreviousColumn( curRow, curCol, true );
1300 //didn't find it, try the next element anccester.
1302 node = node.ParentNode;
1303 } while ( node != null && node.NodeType != XmlNodeType.Element );
1305 //nothing happens, the name doesn't exist as a namespace node.
1310 //the function will find the next namespace node on the given bound element starting with the given column or attribte
1311 // wether to use column or attribute depends on if the bound element is folicated or not.
1312 private bool MoveToNextNamespace( XmlBoundElement be, DataColumn col, XmlAttribute curAttr ) {
1313 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextNamespace(be,col,curAttr)");
1315 if ( be.IsFoliated ) {
1316 XmlAttributeCollection attrs = be.Attributes;
1317 XmlAttribute attr = null;
1318 bool bFound = false;
1319 if ( curAttr == null )
1320 bFound = true; //the first namespace will be the one
1322 if ( curAttr != null )
1323 Debug.Assert( curAttr.NamespaceURI == s_strReservedXmlns );
1325 Debug.Assert( attrs!=null );
1326 int attrInd = attrs.Count;
1327 while ( attrInd > 0 ) {
1329 attr = attrs[attrInd];
1330 if ( bFound && attr.NamespaceURI == s_strReservedXmlns && !DuplicateNS( be, attr.LocalName ) ) {
1334 if ( attr == curAttr )
1338 else {//defoliated so that we need to search through its column
1339 DataRow curRow = be.Row;
1340 if ( curRow == null )
1342 //going through its attribute columns
1343 DataColumn curCol = PreviousColumn( curRow, col, true );
1344 while ( curCol != null ) {
1345 if ( curCol.Namespace == s_strReservedXmlns && !DuplicateNS( be, curCol.ColumnName ) ) {
1346 MoveTo( be, curCol, false );
1349 curCol = PreviousColumn( curRow, curCol, true );
1356 //Caller( DataDocumentXPathNavigator will make sure that the node is at the right position for this call )
1357 internal bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope) {
1358 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToFirstNamespace(namespaceScope)");
1360 _parentOfNS = this._node as XmlBoundElement;
1361 //only need to check with _node, even if _column is not null and its mapping type is element, it can't have attributes
1362 if ( _parentOfNS == null )
1364 XmlNode node = this._node;
1365 XmlBoundElement be = null;
1366 while ( node != null ) {
1367 be = node as XmlBoundElement;
1368 if ( MoveToNextNamespace( be, null, null ) )
1371 if ( namespaceScope == XPathNamespaceScope.Local )
1373 //try the next element anccestor.
1375 node = node.ParentNode;
1376 } while ( node != null && node.NodeType != XmlNodeType.Element );
1378 if ( namespaceScope == XPathNamespaceScope.All ) {
1379 MoveTo( this._doc.attrXml, null, false );
1383 //didn't find one namespace node
1388 //endElem is on the path from startElem to root is enforced by the caller
1389 private bool DuplicateNS( XmlBoundElement endElem, string lname) {
1390 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:DuplicateNS(endElem, lname)");
1391 if ( this._parentOfNS == null || endElem == null )
1393 XmlBoundElement be = this._parentOfNS;
1394 XmlNode node = null;
1395 while ( be != null && be != endElem ) {
1396 if ( GetNamespace( be, lname ) != null )
1400 node = node.ParentNode;
1401 } while ( node != null && node.NodeType != XmlNodeType.Element );
1402 be = node as XmlBoundElement;
1407 //Caller( DataDocumentXPathNavigator will make sure that the node is at the right position for this call )
1408 internal bool MoveToNextNamespace(XPathNamespaceScope namespaceScope) {
1409 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextNamespace(namespaceScope)");
1411 Debug.Assert( _parentOfNS != null );
1412 XmlNode node = this._node;
1413 //first check within the same boundelement
1414 if ( this._column != null ) {
1415 Debug.Assert( this._column.Namespace == s_strReservedXmlns );
1416 if ( namespaceScope == XPathNamespaceScope.Local && _parentOfNS != this._node ) //already outside scope
1418 XmlBoundElement be = this._node as XmlBoundElement;
1419 Debug.Assert( be != null );
1420 DataRow curRow = be.Row;
1421 Debug.Assert( curRow != null );
1422 DataColumn curCol = PreviousColumn( curRow, this._column, true );
1423 while ( curCol != null ) {
1424 if ( curCol.Namespace == s_strReservedXmlns ) {
1425 MoveTo( be, curCol, false );
1428 curCol = PreviousColumn( curRow, curCol, true );
1430 //didn't find it in this loop
1431 if ( namespaceScope == XPathNamespaceScope.Local )
1435 node = node.ParentNode;
1436 } while ( node != null && node.NodeType != XmlNodeType.Element );
1438 else if ( this._node.NodeType == XmlNodeType.Attribute ) {
1439 XmlAttribute attr = (XmlAttribute)(this._node);
1440 Debug.Assert( attr != null );
1441 node = attr.OwnerElement;
1444 if ( namespaceScope == XPathNamespaceScope.Local && _parentOfNS != node ) //already outside scope
1446 if ( MoveToNextNamespace( (XmlBoundElement)node, null, (XmlAttribute)attr ) )
1449 if ( namespaceScope == XPathNamespaceScope.Local )
1452 node = node.ParentNode;
1453 } while ( node != null && node.NodeType != XmlNodeType.Element );
1455 // till now, node should be the next accesstor (bound) element of the element parent of current namespace node (attribute or data column)
1456 while ( node != null ) {
1457 //try the namespace attributes from the same element
1458 XmlBoundElement be = node as XmlBoundElement;
1459 if ( MoveToNextNamespace( be, null, null ) )
1461 //no more namespace attribute under the same element
1463 node = node.ParentNode;
1464 } while ( node != null && node.NodeType == XmlNodeType.Element );
1466 //didn't find the next namespace, thus return
1467 if ( namespaceScope == XPathNamespaceScope.All ) {
1468 MoveTo( this._doc.attrXml, null, false );
1474 [System.Diagnostics.Conditional("DEBUG")]
1475 private void AssertValid() {
1476 // This pointer must be int the document list
1478 this._doc.AssertPointerPresent( this );
1479 if ( this._column != null ) {
1480 // We must be on a de-foliated region
1481 XmlBoundElement rowElem = this._node as XmlBoundElement;
1482 Debug.Assert( rowElem != null );
1484 DataRow row = rowElem.Row;
1485 Debug.Assert( row != null );
1487 //ElementState state = rowElem.ElementState;
1488 //Debug.Assert( state == ElementState.Defoliated || _bNeedFoliated, "Region is accessed using column, but it's state is FOLIATED" );
1490 // We cannot be on a column for which the value is DBNull
1491 DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
1492 Debug.Assert( ! Convert.IsDBNull( row[ this._column, rowVersion ] ) );
1494 // If we are on the Text column, we should always have _fOnValue == true
1495 Debug.Assert( (this._column.ColumnMapping == MappingType.SimpleContent) ? (this._fOnValue == true) : true );
1497 if ( this._column == null )
1498 Debug.Assert( !this._fOnValue );
1501 internal XmlDataDocument Document { get { return _doc; } }
1503 bool IXmlDataVirtualNode.IsInUse() {
1504 //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsInUse()");
1505 return _owner.IsAlive;