| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508 |
- //------------------------------------------------------------------------------
- // <copyright file="XPathNodePointer.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.Data;
- using System.Diagnostics;
- using System.Xml.XPath;
-
- internal sealed class XPathNodePointer : IXmlDataVirtualNode {
- private WeakReference _owner; // Owner of this pointer (an DataDocumentXPathNavigator). When the associated DataDocumentXPathNavigator (the owner) goes away, this XPathNodePointer can go away as well.
- private XmlDataDocument _doc;
- private XmlNode _node;
- private DataColumn _column;
- private bool _fOnValue;
- internal XmlBoundElement _parentOfNS;
- internal static int[] xmlNodeType_To_XpathNodeType_Map;
- internal static string s_strReservedXmlns = "http://www.w3.org/2000/xmlns/";
- internal static string s_strReservedXml = "http://www.w3.org/XML/1998/namespace";
- internal static string s_strXmlNS = "xmlns";
- private bool _bNeedFoliate;
- static XPathNodePointer(){
- #if DEBUG
- int max=0, tempVal=0;
- Array enumValues = Enum.GetValues(typeof(XmlNodeType));
- for ( int i = 0; i < enumValues.Length; i++) {
- tempVal = (int)enumValues.GetValue(i);
- if ( tempVal > max )
- max = tempVal;
- }
- Debug.Assert( max == (int) XmlNodeType.XmlDeclaration );
- #endif
- xmlNodeType_To_XpathNodeType_Map = new int[20];
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.None)] = -1;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Element)] = (int)XPathNodeType.Element;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Attribute)] = (int)XPathNodeType.Attribute;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Text)] = (int)XPathNodeType.Text;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.CDATA)] = (int)XPathNodeType.Text;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.EntityReference)] = -1;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Entity)] = -1;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.ProcessingInstruction)] = (int)XPathNodeType.ProcessingInstruction;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Comment)] = (int)XPathNodeType.Comment;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Document)] = (int)XPathNodeType.Root;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.DocumentType)] = -1;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.DocumentFragment)] = (int)XPathNodeType.Root;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Notation)] = -1;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.Whitespace)] = (int)XPathNodeType.Whitespace;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.SignificantWhitespace)] = (int)XPathNodeType.SignificantWhitespace;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.EndElement)] = -1;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.EndEntity)] = -1;
- xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.XmlDeclaration)] = -1;
- // xmlNodeType_To_XpathNodeType_Map[(int)(XmlNodeType.All)] = -1;
- }
- private XPathNodeType DecideXPNodeTypeForTextNodes( XmlNode node ) {
- //the function can only be called on text like nodes.
- Debug.Assert( XmlDataDocument.IsTextNode( node.NodeType ) );
- XPathNodeType xnt = XPathNodeType.Whitespace;
- while( node != null ) {
- switch( node.NodeType ) {
- case XmlNodeType.Whitespace :
- break;
- case XmlNodeType.SignificantWhitespace :
- xnt = XPathNodeType.SignificantWhitespace;
- break;
- case XmlNodeType.Text :
- case XmlNodeType.CDATA :
- return XPathNodeType.Text;
- default :
- return xnt;
- }
- node = this._doc.SafeNextSibling(node);
- }
- return xnt;
- }
-
- private XPathNodeType ConvertNodeType( XmlNode node ) {
- int xnt = -1;
- if ( XmlDataDocument.IsTextNode( node.NodeType ) )
- return DecideXPNodeTypeForTextNodes( node );
- xnt = xmlNodeType_To_XpathNodeType_Map[(int)(node.NodeType)];
- if ( xnt == (int) XPathNodeType.Attribute ) {
- if ( node.NamespaceURI == s_strReservedXmlns )
- return XPathNodeType.Namespace;
- else
- return XPathNodeType.Attribute;
- }
- Debug.Assert( xnt != -1 );
- return (XPathNodeType)xnt;
- }
- private bool IsNamespaceNode( XmlNodeType nt, string ns ) {
- if ( nt == XmlNodeType.Attribute && ns == s_strReservedXmlns )
- return true;
- return false;
- }
- //when the constructor is called, the node has to be a valid XPath node at the valid location ( for example, the first
- //text/WS/SWS/CData nodes of a series continuous text-like nodes.
- internal XPathNodePointer( DataDocumentXPathNavigator owner, XmlDataDocument doc, XmlNode node )
- : this ( owner, doc, node, null, false, null ){
- }
- internal XPathNodePointer( DataDocumentXPathNavigator owner, XPathNodePointer pointer )
- : this ( owner, pointer._doc, pointer._node, pointer._column, pointer._fOnValue, pointer._parentOfNS ) {
- }
- private XPathNodePointer( DataDocumentXPathNavigator owner, XmlDataDocument doc, XmlNode node, DataColumn c, bool bOnValue, XmlBoundElement parentOfNS ) {
- Debug.Assert( owner != null );
- this._owner = new WeakReference( owner );
- this._doc = doc;
- this._node = node;
- this._column = c;
- this._fOnValue = bOnValue;
- this._parentOfNS = parentOfNS;
- // Add this pointer to the document so it will be updated each time region changes it's foliation state.
- this._doc.AddPointer( (IXmlDataVirtualNode)this );
- _bNeedFoliate = false;
- AssertValid();
- }
- internal XPathNodePointer Clone( DataDocumentXPathNavigator owner ){
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Clone");
- RealFoliate();
- return new XPathNodePointer( owner, this ) ;
- }
- internal bool IsEmptyElement {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsEmptyElement");
- AssertValid();
- if (_node != null && _column == null) {
- if (_node.NodeType == XmlNodeType.Element) {
- return((XmlElement)_node).IsEmpty;
- }
- }
- return false;
- }
- }
- internal XPathNodeType NodeType {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:NodeType");
- RealFoliate();
- AssertValid();
- if (this._node == null) {
- return XPathNodeType.All;
- }
- else if (this._column == null) {
- return ConvertNodeType(this._node);
- }
- else if (this._fOnValue) {
- return XPathNodeType.Text;
- }
- else if (this._column.ColumnMapping == MappingType.Attribute) {
- if ( this._column.Namespace == s_strReservedXmlns )
- return XPathNodeType.Namespace;
- else
- return XPathNodeType.Attribute;
- }
- else //
- return XPathNodeType.Element;
- }
- }
- //Microsoft: From CodeReview: Perf: We should have another array similar w/
- // xmlNodeType_To_XpathNodeType_Map that will return String.Empty for everything but the element and
- // attribute case.
- internal string LocalName {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:LocalName");
- RealFoliate();
- AssertValid();
- if (this._node == null) {
- return string.Empty;
- }
- else if (this._column == null) {
- XmlNodeType nt = this._node.NodeType;
- if ( IsNamespaceNode( nt, this._node.NamespaceURI ) && this._node.LocalName == s_strXmlNS )
- return string.Empty;
- if ( nt == XmlNodeType.Element || nt == XmlNodeType.Attribute || nt == XmlNodeType.ProcessingInstruction )
- return _node.LocalName;
- return string.Empty;
- }
- else if (this._fOnValue) {
- return String.Empty;
- }
- else //when column is not null
- return _doc.NameTable.Add(_column.EncodedColumnName);
- }
- }
- //note that, we've have lost the prefix in this senario ( defoliation will toss prefix away. )
- internal string Name {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Name");
- RealFoliate();
- AssertValid();
- if (this._node == null) {
- return string.Empty;
- }
- else if (this._column == null) {
- XmlNodeType nt = this._node.NodeType;
- if ( IsNamespaceNode( nt, this._node.NamespaceURI ) ) {
- if ( this._node.LocalName == s_strXmlNS )
- return string.Empty;
- else
- return this._node.LocalName;
- }
- if ( nt == XmlNodeType.Element || nt == XmlNodeType.Attribute || nt == XmlNodeType.ProcessingInstruction )
- return _node.Name;
- return string.Empty;
- }
- else if (this._fOnValue) {
- return String.Empty;
- }
- else { //when column is not null
- //we've lost prefix in this senario.
- return _doc.NameTable.Add(_column.EncodedColumnName);
- }
- }
- }
-
- internal string NamespaceURI {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:NamespaceURI");
- RealFoliate();
- AssertValid();
- if (this._node == null) {
- return string.Empty;
- }
- else if (this._column == null) {
- XPathNodeType xnt = ConvertNodeType( this._node );
- if ( xnt == XPathNodeType.Element || xnt == XPathNodeType.Root || xnt == XPathNodeType.Attribute )
- return _node.NamespaceURI;
- return string.Empty;
- }
- else if (this._fOnValue) {
- return string.Empty;
- }
- else { //When column is not null
- if ( _column.Namespace == s_strReservedXmlns )
- //namespace nodes has empty string as namespaceURI
- return string.Empty;
- return _doc.NameTable.Add(_column.Namespace);
- }
- }
- }
- //
- internal string Prefix {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Prefix");
- RealFoliate();
- AssertValid();
- if (this._node == null) {
- return string.Empty;
- }
- else if (this._column == null) {
- if ( IsNamespaceNode( this._node.NodeType, this._node.NamespaceURI ) )
- return string.Empty;
- return _node.Prefix;
- }
- return string.Empty;
- }
- }
- internal string Value {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Value");
- RealFoliate();
- AssertValid();
- if (this._node == null)
- return null;
- else if (this._column == null) {
- string strRet = this._node.Value;
- if ( XmlDataDocument.IsTextNode( this._node.NodeType ) ) {
- //concatenate adjacent textlike nodes
- XmlNode parent = this._node.ParentNode;
- if ( parent == null )
- return strRet;
- XmlNode n = _doc.SafeNextSibling(this._node);
- while ( n != null && XmlDataDocument.IsTextNode( n.NodeType ) ) {
- strRet += n.Value;
- n = _doc.SafeNextSibling(n);
- }
- }
- return strRet;
- }
- else if (this._column.ColumnMapping == MappingType.Attribute || this._fOnValue) {
- DataRow row = this.Row;
- DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
- object value = row[ this._column, rowVersion ];
- if ( ! Convert.IsDBNull( value ) )
- return this._column.ConvertObjectToXml( value );
- return null;
- }
- else
- //
- return null;
- }
- }
- internal string InnerText {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:InnerText");
- RealFoliate();
- AssertValid();
- if (this._node == null) {
- return string.Empty;
- }
- else if (this._column == null) {
- //
- if ( this._node.NodeType == XmlNodeType.Document ) {
- //document node's region should always be uncompressed
- XmlElement rootElem = ((XmlDocument)this._node).DocumentElement;
- if ( rootElem != null )
- return rootElem.InnerText;
- return string.Empty;
- }
- else
- return this._node.InnerText;
- }
- else {
- DataRow row = this.Row;
- DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
- object value = row[ this._column, rowVersion ];
- if ( ! Convert.IsDBNull( value ) )
- return this._column.ConvertObjectToXml( value );
- return string.Empty;
- }
- }
- }
- internal String BaseURI {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:BaseURI");
- RealFoliate();
- if ( this._node != null )
- return this._node.BaseURI;
- return String.Empty;
- }
- }
- internal String XmlLang {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:XmlLang");
- RealFoliate();
- XmlNode curNode = this._node;
- XmlBoundElement curBoundElem = null;
- object colVal = null;
- while ( curNode != null ) {
- //
- curBoundElem = curNode as XmlBoundElement;
- if ( curBoundElem != null ) {
- //this._doc.Foliate( curBoundElem, ElementState.WeakFoliation );
- if ( curBoundElem.ElementState == ElementState.Defoliated ) {
- //if not foliated, going through the columns to get the xml:lang
- DataRow row = curBoundElem.Row;
- foreach( DataColumn col in row.Table.Columns ) {
- if ( col.Prefix == "xml" && col.EncodedColumnName == "lang" ) {
- colVal = row[col];
- if ( colVal == DBNull.Value )
- break; //goto its ancesstors
- return (String) colVal;
- }
- }
- }
- else {
- //if folicated, get the attribute directly
- if ( curBoundElem.HasAttribute( "xml:lang" ) )
- return curBoundElem.GetAttribute( "xml:lang" );
- }
- }
- if ( curNode.NodeType == XmlNodeType.Attribute )
- curNode = ((XmlAttribute)curNode).OwnerElement;
- else
- curNode = curNode.ParentNode;
- }
- return String.Empty;
- }
- }
-
- private XmlBoundElement GetRowElement() {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetRowElement()");
- //AssertValid();
- XmlBoundElement rowElem;
- if ( this._column != null ) {
- rowElem = this._node as XmlBoundElement;
- Debug.Assert( rowElem != null );
- Debug.Assert( rowElem.Row != null );
- return rowElem;
- }
- _doc.Mapper.GetRegion( this._node, out rowElem );
- return rowElem;
- }
- //
- private DataRow Row {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Row");
- //AssertValid();
- XmlBoundElement rowElem = GetRowElement();
- if ( rowElem == null )
- return null;
- Debug.Assert( rowElem.Row != null );
- return rowElem.Row;
- }
- }
- internal bool MoveTo( XPathNodePointer pointer ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveTo(pointer)");
- AssertValid();
- if ( this._doc != pointer._doc )
- return false;
- /*
- XmlDataDocument docOld = this._doc;
- XmlDataDocument docNew = pointer._doc;
- if ( docNew != docOld ) {
- this._doc.RemovePointer( this );
- this._doc = pointer._doc;
- this._doc.AddPointer( this );
- }
- */
- this._node = pointer._node;
- this._column = pointer._column;
- this._fOnValue = pointer._fOnValue;
- this._bNeedFoliate = pointer._bNeedFoliate;
- AssertValid();
- return true;
- }
- private void MoveTo( XmlNode node ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveTo(node)");
- //AssertValid();
- // Should not move outside of this document
- Debug.Assert( node == this._doc || node.OwnerDocument == this._doc );
- this._node = node;
- this._column = null;
- this._fOnValue = false;
- //AssertValid();
- }
- private void MoveTo( XmlNode node, DataColumn column, bool _fOnValue ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveTo(node, column, fOnValue)");
- //AssertValid();
- // Should not move outside of this document
- Debug.Assert( node == this._doc || node.OwnerDocument == this._doc );
- this._node = node;
- this._column = column;
- this._fOnValue = _fOnValue;
- //AssertValid();
- }
- private bool IsFoliated( XmlNode node ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsFoliated(node)");
- //AssertValid();
- if (node != null && node is XmlBoundElement)
- return((XmlBoundElement)node).IsFoliated;
- return true;
- }
- private int ColumnCount( DataRow row, bool fAttribute ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:ColumnCount(row,fAttribute)");
- DataColumn c = null;
- int count = 0;
- while ((c = NextColumn( row, c, fAttribute )) != null) {
- if ( c.Namespace != s_strReservedXmlns )
- count++;
- }
- return count;
- }
- internal int AttributeCount {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:AttributeCount");
- RealFoliate();
- AssertValid();
- if (_node != null) {
- if (_column == null && _node.NodeType == XmlNodeType.Element) {
- if (!IsFoliated( _node ))
- return ColumnCount( Row, true );
- else {
- int nc = 0;
- foreach ( XmlAttribute attr in _node.Attributes ) {
- if ( attr.NamespaceURI != s_strReservedXmlns )
- nc++;
- }
- return nc;
- }
- }
- }
- return 0;
- }
- }
- internal DataColumn NextColumn( DataRow row, DataColumn col, bool fAttribute ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:NextColumn(row,col,fAttribute)");
- if (row.RowState == DataRowState.Deleted)
- return null;
- DataTable table = row.Table;
- DataColumnCollection columns = table.Columns;
- int iColumn = (col != null) ? col.Ordinal + 1 : 0;
- int cColumns = columns.Count;
- DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
- for (; iColumn < cColumns; iColumn++) {
- DataColumn c = columns[iColumn];
- if (!_doc.IsNotMapped( c ) && (c.ColumnMapping == MappingType.Attribute) == fAttribute && ! Convert.IsDBNull( row[c, rowVersion] ) )
- return c;
- }
- return null;
- }
- internal DataColumn PreviousColumn( DataRow row, DataColumn col, bool fAttribute ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:PreviousColumn(row,col,fAttribute)");
- if (row.RowState == DataRowState.Deleted)
- return null;
- DataTable table = row.Table;
- DataColumnCollection columns = table.Columns;
- int iColumn = (col != null) ? col.Ordinal - 1 : columns.Count - 1;
- int cColumns = columns.Count;
- DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
- for (; iColumn >= 0; iColumn--) {
- DataColumn c = columns[iColumn];
- if (!_doc.IsNotMapped( c ) && (c.ColumnMapping == MappingType.Attribute) == fAttribute && !Convert.IsDBNull( row[c, rowVersion] ) )
- return c;
- }
- return null;
- }
- internal bool MoveToAttribute( string localName, string namespaceURI ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToAttribute(localName, namespaceURI)");
- RealFoliate();
- AssertValid();
- if ( namespaceURI == s_strReservedXmlns )
- return false;
- if (_node != null) {
- //_column.ColumnMapping checkin below is not really needed since the pointer should be pointing at the node before this
- // function should even be called ( there is always a call MoveToOwnerElement() before MoveToAttribute(..)
- if ((_column == null || _column.ColumnMapping == MappingType.Attribute) && _node.NodeType == XmlNodeType.Element) {
- if (!IsFoliated( _node )) {
- DataColumn c = null;
- while ((c = NextColumn( Row, c, true )) != null) {
- if (c.EncodedColumnName == localName && c.Namespace == namespaceURI) {
- MoveTo( _node, c, false );
- return true;
- }
- }
- }
- else {
- Debug.Assert( _node.Attributes != null );
- XmlNode n = _node.Attributes.GetNamedItem(localName, namespaceURI);
- if (n != null) {
- MoveTo( n, null, false );
- return true;
- }
- }
- }
- }
- return false;
- }
-
- internal bool MoveToNextAttribute( bool bFirst ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextAttribute(bFirst)");
- //
- RealFoliate();
- AssertValid();
- if (_node != null) {
- if ( bFirst && ( _column != null || _node.NodeType != XmlNodeType.Element ) )
- return false;
- if ( !bFirst ) {
- if ( _column != null && _column.ColumnMapping != MappingType.Attribute )
- return false;
- if ( _column == null && _node.NodeType != XmlNodeType.Attribute )
- return false;
- }
- if ( !IsFoliated( _node ) ) {
- DataColumn c = _column;
- while ( ( c = NextColumn( Row, c, true ) ) != null ) {
- if ( c.Namespace != s_strReservedXmlns ) {
- MoveTo( _node, c, false );
- return true;
- }
- }
- return false;
- }
- else {
- if ( bFirst ) {
- XmlAttributeCollection attrs = _node.Attributes;
- foreach ( XmlAttribute attr in attrs ) {
- if ( attr.NamespaceURI != s_strReservedXmlns ) {
- MoveTo( attr, null, false );
- return true;
- }
- }
- }
- else {
- XmlAttributeCollection attrs = ((XmlAttribute)_node).OwnerElement.Attributes;
- bool bFound = false;
- foreach ( XmlAttribute attr in attrs ) {
- if ( bFound && attr.NamespaceURI != s_strReservedXmlns ) {
- MoveTo( attr, null, false );
- return true;
- }
- if ( attr == _node )
- bFound = true;
- }
- }
- }
- }
- return false;
- }
-
- private bool IsValidChild( XmlNode parent, XmlNode child ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsValidChild(parent,child)");
- int xntChildInt = xmlNodeType_To_XpathNodeType_Map[(int)(child.NodeType)];
- if ( xntChildInt == -1 )
- return false;
- int xntInt = xmlNodeType_To_XpathNodeType_Map[(int)(parent.NodeType)];
- Debug.Assert( xntInt != -1 );
- switch ( xntInt ) {
- case (int)XPathNodeType.Root:
- return ( xntChildInt == (int)XPathNodeType.Element ||
- xntChildInt == (int)XPathNodeType.Comment ||
- xntChildInt == (int)XPathNodeType.ProcessingInstruction );
- case (int)XPathNodeType.Element:
- return ( xntChildInt == (int)XPathNodeType.Element ||
- xntChildInt == (int)XPathNodeType.Text ||
- xntChildInt == (int)XPathNodeType.Comment ||
- xntChildInt == (int)XPathNodeType.Whitespace ||
- xntChildInt == (int)XPathNodeType.SignificantWhitespace ||
- xntChildInt == (int)XPathNodeType.ProcessingInstruction );
- default :
- return false;
- }
- }
- private bool IsValidChild( XmlNode parent, DataColumn c ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsValidChild(parent,c)");
- int xntInt = xmlNodeType_To_XpathNodeType_Map[(int)(parent.NodeType)];
- Debug.Assert( xntInt != -1 );
- switch ( xntInt ) {
- case (int)XPathNodeType.Root:
- return c.ColumnMapping == MappingType.Element;
- case (int)XPathNodeType.Element:
- return ( c.ColumnMapping == MappingType.Element || c.ColumnMapping == MappingType.SimpleContent );
- default :
- return false;
- }
- }
-
- internal bool MoveToNextSibling() {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextSibling()");
- RealFoliate();
- AssertValid();
- if (_node != null) {
- if ( _column != null ) {
- if ( _fOnValue ) {
- // _fOnValue could be true only when the column is mapped as simplecontent or element
- Debug.Assert( _column.ColumnMapping != MappingType.Attribute && _column.ColumnMapping != MappingType.Hidden );
- return false;
- }
- DataRow curRow = Row;
- DataColumn c = NextColumn( curRow, _column, false );
- while ( c != null ) {
- if ( IsValidChild( _node, c ) ) {
- MoveTo( this._node, c, _doc.IsTextOnly(c));
- return true;
- }
- c = NextColumn( curRow, c, false );
- }
- XmlNode n = _doc.SafeFirstChild( _node );
- if (n != null) {
- MoveTo( n );
- return true;
- }
- }
- else {
- XmlNode n = _node;
- XmlNode parent = _node.ParentNode;
- if ( parent == null )
- return false;
- bool bTextLike = XmlDataDocument.IsTextNode( _node.NodeType );
- do {
- do {
- n = _doc.SafeNextSibling(n);
- } while ( n != null && bTextLike && XmlDataDocument.IsTextNode( n.NodeType ));
- } while ( n != null && !IsValidChild(parent, n) );
- if (n != null) {
- MoveTo(n);
- return true;
- }
- }
- }
- return false;
- }
-
- internal bool MoveToPreviousSibling() {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToPreviousSibling()");
- RealFoliate();
- AssertValid();
- if (_node != null) {
- if (_column != null) {
- if (_fOnValue)
- return false;
- DataRow curRow = Row;
- DataColumn c = PreviousColumn( curRow, _column, false );
- while ( c != null ) {
- if ( IsValidChild(_node,c)) {
- MoveTo( _node, c, _doc.IsTextOnly(c) );
- return true;
- }
- c = PreviousColumn( curRow, c , false );
- }
- }
- else {
- XmlNode n = _node;
- XmlNode parent = _node.ParentNode;
- if ( parent == null )
- return false;
- bool bTextLike = XmlDataDocument.IsTextNode( _node.NodeType );
- do {
- do {
- n = _doc.SafePreviousSibling( n );
- } while ( n != null && bTextLike && XmlDataDocument.IsTextNode( n.NodeType ) );
- } while ( n != null && !IsValidChild(parent, n) );
- if (n != null) {
- MoveTo(n);
- return true;
- }
- if (!IsFoliated( parent ) && (parent is XmlBoundElement)) {
- DataRow row = ((XmlBoundElement)parent).Row;
- if (row != null) {
- DataColumn c = PreviousColumn( row, null, false );
- if (c != null) {
- MoveTo( parent, c, _doc.IsTextOnly(c) );
- return true;
- }
- }
- }
- }
- }
- return false;
- }
- internal bool MoveToFirst() {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToFirst()");
- RealFoliate();
- AssertValid();
- if (_node != null) {
- DataRow curRow = null;
- XmlNode parent = null;
- if (_column != null) {
- curRow = Row;
- parent = _node;
- }
- else {
- parent = _node.ParentNode;
- if ( parent == null )
- return false;
- if ( !IsFoliated( parent ) && (parent is XmlBoundElement) )
- curRow = ((XmlBoundElement)parent).Row;
- }
- //first check with the columns in the row
- if ( curRow != null ) {
- DataColumn c = NextColumn( curRow, null, false );
- while ( c != null ) {
- if ( IsValidChild( _node, c ) ) {
- MoveTo( _node, c, _doc.IsTextOnly( c ) );
- return true;
- }
- c = NextColumn( curRow, c, false );
- }
- }
- //didn't find a valid column or maybe already Foliated, go through its children nodes
- XmlNode n = _doc.SafeFirstChild( parent );
- while ( n != null ) {
- if ( IsValidChild( parent, n ) ) {
- MoveTo( n );
- return true;
- }
- n = _doc.SafeNextSibling( n );
- }
- }
- return false;
- }
- internal bool HasChildren {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:HasChildren");
- RealFoliate();
- AssertValid();
- if (_node == null)
- return false;
- if (_column != null) {
- if ( _column.ColumnMapping == MappingType.Attribute || _column.ColumnMapping == MappingType.Hidden )
- return false;
- return !_fOnValue;
- }
- if (!IsFoliated( _node )) {
- // find virtual column elements first
- DataRow curRow = Row;
- DataColumn c = NextColumn( curRow, null, false );
- while ( c != null ) {
- if ( IsValidChild( _node, c) )
- return true;
- c = NextColumn( curRow, c, false );
- }
- }
- // look for anything
- XmlNode n = _doc.SafeFirstChild( _node );
- while ( n != null ) {
- if ( IsValidChild( _node, n ) )
- return true;
- n = _doc.SafeNextSibling( n );
- }
- return false;
- }
- }
-
- internal bool MoveToFirstChild() {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToFirstChild()");
- RealFoliate();
- AssertValid();
- if (_node == null)
- return false;
- if (_column != null) {
- if ( _column.ColumnMapping == MappingType.Attribute || _column.ColumnMapping == MappingType.Hidden )
- return false;
- if (_fOnValue) //text node has no children to move to
- return false;
- _fOnValue = true;
- return true;
- }
- if (!IsFoliated( _node )) {
- // find virtual column elements first
- DataRow curRow = Row;
- DataColumn c = NextColumn( curRow, null, false );
- while ( c != null ) {
- if ( IsValidChild( _node, c) ) {
- MoveTo( _node, c, _doc.IsTextOnly(c) );
- return true;
- }
- c = NextColumn( curRow, c, false );
- }
- }
- // look for anything
- XmlNode n = _doc.SafeFirstChild( _node );
- while ( n != null ) {
- if ( IsValidChild( _node, n ) ) {
- MoveTo(n);
- return true;
- }
- n = _doc.SafeNextSibling( n );
- }
- return false;
- }
-
- //this version of MoveToParent will consider Attribute type position and move to its owner element
- //
- internal bool MoveToParent() {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToParent()");
- RealFoliate();
- AssertValid();
- if ( NodeType == XPathNodeType.Namespace ) {
- MoveTo( _parentOfNS );
- return true;
- }
- if (_node != null) {
- if (_column != null) {
- if (_fOnValue && !_doc.IsTextOnly(_column)) {
- MoveTo( _node, _column, false );
- return true;
- }
- MoveTo( _node, null, false );
- return true;
- }
- else {
- XmlNode n = null;
- if ( _node.NodeType == XmlNodeType.Attribute )
- n = ((XmlAttribute)_node).OwnerElement;
- else
- n = _node.ParentNode;
- if (n != null) {
- MoveTo(n);
- return true;
- }
- }
- }
- return false;
- }
- private XmlNode GetParent( XmlNode node ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetParent(node)");
- XPathNodeType xnt = ConvertNodeType( node );
- if ( xnt == XPathNodeType.Namespace ) {
- Debug.Assert( _parentOfNS != null );
- return _parentOfNS;
- }
- if ( xnt == XPathNodeType.Attribute )
- return ((XmlAttribute)node).OwnerElement;
- return node.ParentNode;
- }
-
- internal void MoveToRoot() {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToRoot()");
- XmlNode node = this._node;
- XmlNode parent = this._node;
- while ( parent != null ) {
- node = parent;
- parent = GetParent(parent);
- }
- this._node = node;
- this._column = null;
- this._fOnValue = false;
- AssertValid();
- }
-
- internal bool IsSamePosition( XPathNodePointer pointer ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsSamePosition(pointer)");
- RealFoliate();
- pointer.RealFoliate();
- AssertValid();
- pointer.AssertValid();
- if (_column == null && pointer._column == null)
- return ( pointer._node == this._node && pointer._parentOfNS == this._parentOfNS );
- return ( pointer._doc == this._doc
- && pointer._node == this._node
- && pointer._column == this._column
- && pointer._fOnValue == this._fOnValue
- && pointer._parentOfNS == this._parentOfNS );
- }
- private XmlNodeOrder CompareNamespacePosition( XPathNodePointer other ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:CompareNamespacePostion(other)");
- XPathNodePointer xp1 = this.Clone((DataDocumentXPathNavigator)(this._owner.Target));
- XPathNodePointer xp2 = other.Clone((DataDocumentXPathNavigator)(other._owner.Target));
- while ( xp1.MoveToNextNamespace(XPathNamespaceScope.All) ) {
- if ( xp1.IsSamePosition( other ) )
- return XmlNodeOrder.Before;
- }
- return XmlNodeOrder.After;
- }
-
- private static XmlNode GetRoot( XmlNode node, ref int depth ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetRoot(node, depth)");
- depth = 0;
- XmlNode curNode = node;
- XmlNode parent = ( ( curNode.NodeType == XmlNodeType.Attribute ) ? ( ((XmlAttribute)curNode).OwnerElement ) : ( curNode.ParentNode ) );
- for ( ; parent != null; depth++ ) {
- curNode = parent;
- parent = curNode.ParentNode; // no need to check for attribute since navigator can't be built on its children or navigate to its children
- }
- return curNode;
- }
- internal XmlNodeOrder ComparePosition( XPathNodePointer other ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:ComparePosition(other)");
- RealFoliate();
- other.RealFoliate();
- Debug.Assert( other != null );
- if ( IsSamePosition( other ) )
- return XmlNodeOrder.Same;
- XmlNode curNode1 = null, curNode2 = null;
- //deal with namespace node first
- if ( this.NodeType == XPathNodeType.Namespace && other.NodeType == XPathNodeType.Namespace ) {
- if ( this._parentOfNS == other._parentOfNS )
- return this.CompareNamespacePosition( other );
- //if not from the same parent
- curNode1 = this._parentOfNS;
- curNode2 = other._parentOfNS;
- }
- else if ( this.NodeType == XPathNodeType.Namespace ) {
- Debug.Assert( other.NodeType != XPathNodeType.Namespace );
- if ( this._parentOfNS == other._node ) {
- //from the same region, NS nodes come before all other nodes
- if ( other._column == null )
- return XmlNodeOrder.After;
- else
- return XmlNodeOrder.Before;
- }
- //if not from the same region
- curNode1 = this._parentOfNS;
- curNode2 = other._node;
- }
- else if ( other.NodeType == XPathNodeType.Namespace ) {
- Debug.Assert( this.NodeType != XPathNodeType.Namespace );
- if ( this._node == other._parentOfNS ) {
- //from the same region
- if ( this._column == null )
- return XmlNodeOrder.Before;
- else
- return XmlNodeOrder.After;
- }
- //if not from the same region
- curNode1 = this._node;
- curNode2 = other._parentOfNS;
- }
- else {
- if ( this._node == other._node ) {
- //compare within the same region
- if ( this._column == other._column ) {
- //one is the children of the other
- Debug.Assert( this._fOnValue != other._fOnValue );
- if ( this._fOnValue )
- return XmlNodeOrder.After;
- else
- return XmlNodeOrder.Before;
- }
- else {
- Debug.Assert( this.Row == other.Row ); //in the same row
- if ( this._column == null )
- return XmlNodeOrder.Before;
- else if ( other._column == null )
- return XmlNodeOrder.After;
- else if ( this._column.Ordinal < other._column.Ordinal )
- return XmlNodeOrder.Before;
- else
- return XmlNodeOrder.After;
- }
- }
- curNode1 = this._node;
- curNode2 = other._node;
-
- }
- Debug.Assert( curNode1 != null );
- Debug.Assert( curNode2 != null );
- if (curNode1 == null || curNode2 == null) {
- return XmlNodeOrder.Unknown;
- }
- int depth1 = -1, depth2 = -1;
- XmlNode root1 = XPathNodePointer.GetRoot( curNode1, ref depth1 );
- XmlNode root2 = XPathNodePointer.GetRoot( curNode2, ref depth2 );
- if ( root1 != root2 )
- return XmlNodeOrder.Unknown;
- if ( depth1 > depth2 ) {
- while ( curNode1 != null && depth1 > depth2 ) {
- curNode1 = ( ( curNode1.NodeType == XmlNodeType.Attribute ) ? ( ((XmlAttribute)curNode1).OwnerElement ) : ( curNode1.ParentNode ) );
- depth1--;
- }
- if ( curNode1 == curNode2 )
- return XmlNodeOrder.After;
- }
- else if ( depth2 > depth1 ) {
- while ( curNode2 != null && depth2 > depth1 ) {
- curNode2 = ( ( curNode2.NodeType == XmlNodeType.Attribute ) ? ( ((XmlAttribute)curNode2).OwnerElement ) : ( curNode2.ParentNode ) );
- depth2--;
- }
- if ( curNode1 == curNode2 )
- return XmlNodeOrder.Before;
- }
- XmlNode parent1 = GetParent(curNode1);
- XmlNode parent2 = GetParent(curNode2);
- XmlNode nextNode = null;
- while ( parent1 != null && parent2 != null ) {
- if ( parent1 == parent2 ) {
- while (curNode1 != null ) {
- nextNode = curNode1.NextSibling;
- if ( nextNode == curNode2 )
- return XmlNodeOrder.Before;
- curNode1 = nextNode;
- }
- return XmlNodeOrder.After;
- }
- curNode1 = parent1;
- curNode2 = parent2;
- parent1 = curNode1.ParentNode;
- parent2 = curNode2.ParentNode;
- }
-
- //logically, we shouldn't reach here
- Debug.Assert( false );
- return XmlNodeOrder.Unknown;
- }
-
- internal XmlNode Node {
- get {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:Node");
- RealFoliate();
- AssertValid();
- if ( this._node == null )
- return null;
- XmlBoundElement rowElem = GetRowElement();
- if ( rowElem != null ) {
- //lock ( this._doc.pointers ) {
- bool wasFoliationEnabled = this._doc.IsFoliationEnabled;
- this._doc.IsFoliationEnabled = true;
- this._doc.Foliate( rowElem, ElementState.StrongFoliation );
- this._doc.IsFoliationEnabled = wasFoliationEnabled;
- //}
- }
- RealFoliate();
- AssertValid();
- return this._node;
- }
- }
- bool IXmlDataVirtualNode.IsOnNode( XmlNode nodeToCheck ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsOnNode(nodeToCheck)");
- RealFoliate();
- return nodeToCheck == this._node;
- }
- bool IXmlDataVirtualNode.IsOnColumn( DataColumn col ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsOnColumn(col)");
- RealFoliate();
- return col == this._column;
- }
-
- void IXmlDataVirtualNode.OnFoliated( XmlNode foliatedNode ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:OnFoliated(foliatedNode)");
- // update the pointer if the element node has been foliated
- if (_node == foliatedNode) {
- // if already on this node, nothing to do!
- if (_column == null)
- return;
- _bNeedFoliate = true;
- }
- }
- private void RealFoliate() {
- if ( !_bNeedFoliate )
- return;
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:RealFoliate()");
- _bNeedFoliate = false;
- Debug.Assert( this._column != null );
-
- XmlNode n = null;
- if (_doc.IsTextOnly( _column ))
- n = _node.FirstChild;
- else {
- if (_column.ColumnMapping == MappingType.Attribute) {
- n = _node.Attributes.GetNamedItem( _column.EncodedColumnName, _column.Namespace );
- }
- else {
- for (n = _node.FirstChild; n != null; n = n.NextSibling) {
- if (n.LocalName == _column.EncodedColumnName && n.NamespaceURI == _column.Namespace)
- break;
- }
- }
- if (n != null && _fOnValue)
- n = n.FirstChild;
- }
- if (n == null)
- throw new InvalidOperationException(Res.GetString(Res.DataDom_Foliation));
- // Cannot use MoveTo( n ); b/c the initial state for MoveTo is invalid (region is foliated but this is not)
- this._node = n;
- this._column = null;
- this._fOnValue = false;
- AssertValid();
- _bNeedFoliate = false;
- }
- //The function only helps to find out if there is a namespace declaration of given name is defined on the given node
- //It will not check the accestors of the given node.
- private string GetNamespace( XmlBoundElement be, string name ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetNamespace(be,name)");
- if ( be == null )
- return null;
- XmlAttribute attr = null;
- if ( be.IsFoliated ) {
- attr = be.GetAttributeNode ( name, s_strReservedXmlns );
- if ( attr != null )
- return attr.Value;
- else
- return null;
- }
- else { //defoliated so that we need to search through its column
- DataRow curRow = be.Row;
- if ( curRow == null )
- return null;
- //going through its attribute columns
- DataColumn curCol = PreviousColumn( curRow, null, true );
- while ( curCol != null ) {
- if ( curCol.Namespace == s_strReservedXmlns ) {
- //
- DataRowVersion rowVersion = ( curRow.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
- return curCol.ConvertObjectToXml( curRow[curCol,rowVersion] );
- }
- curCol = PreviousColumn( curRow, curCol, true );
- }
- return null;
- }
- }
-
- internal string GetNamespace(string name) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetNamespace(name)");
- //we are checking the namespace nodes backwards comparing its normal order in DOM tree
- if ( name == "xml" )
- return s_strReservedXml;
- if ( name == "xmlns" )
- return s_strReservedXmlns;
- if ( name != null && name.Length == 0 )
- name = "xmlns";
- RealFoliate();
- XmlNode node = _node;
- XmlNodeType nt = node.NodeType;
- String retVal = null;
- while ( node != null ) {
- //first identify an element node in the ancestor + itself
- while ( node != null && ( ( nt = node.NodeType ) != XmlNodeType.Element ) ) {
- if ( nt == XmlNodeType.Attribute )
- node = ((XmlAttribute)node).OwnerElement;
- else
- node = node.ParentNode;
- }
- //found one -- inside if
- if ( node != null ) {
- //must be element node
- retVal = GetNamespace((XmlBoundElement)node, name);
- if ( retVal != null )
- return retVal;
- //didn't find it, try the next parentnode
- node = node.ParentNode;
- }
- }
- //nothing happens, then return string.empty.
- return string.Empty;
- }
- internal bool MoveToNamespace(string name) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNamespace(name)");
- _parentOfNS = this._node as XmlBoundElement;
- //only need to check with _node, even if _column is not null and its mapping type is element, it can't have attributes
- if ( _parentOfNS == null )
- return false;
- string attrName = name;
- if ( attrName == "xmlns" )
- attrName = "xmlns:xmlns";
- if ( attrName != null && attrName.Length == 0 )
- attrName = "xmlns";
- RealFoliate();
- XmlNode node = this._node;
- XmlNodeType nt = node.NodeType;
- XmlAttribute attr = null;
- XmlBoundElement be = null;
- while ( node != null ) {
- //check current element node
- be = node as XmlBoundElement;
- if ( be != null ) {
- if ( be.IsFoliated ) {
- attr = be.GetAttributeNode ( name, s_strReservedXmlns );
- if ( attr != null ) {
- MoveTo( attr );
- return true;
- }
- }
- else {//defoliated so that we need to search through its column
- DataRow curRow = be.Row;
- if ( curRow == null )
- return false;
- //going through its attribute columns
- DataColumn curCol = PreviousColumn( curRow, null, true );
- while ( curCol != null ) {
- if ( curCol.Namespace == s_strReservedXmlns && curCol.ColumnName == name ) {
- MoveTo( be, curCol, false );
- return true;
- }
- curCol = PreviousColumn( curRow, curCol, true );
- }
- }
- }
- //didn't find it, try the next element anccester.
- do {
- node = node.ParentNode;
- } while ( node != null && node.NodeType != XmlNodeType.Element );
- }
- //nothing happens, the name doesn't exist as a namespace node.
- _parentOfNS = null;
- return false;
- }
- //the function will find the next namespace node on the given bound element starting with the given column or attribte
- // wether to use column or attribute depends on if the bound element is folicated or not.
- private bool MoveToNextNamespace( XmlBoundElement be, DataColumn col, XmlAttribute curAttr ) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextNamespace(be,col,curAttr)");
- if ( be != null ) {
- if ( be.IsFoliated ) {
- XmlAttributeCollection attrs = be.Attributes;
- XmlAttribute attr = null;
- bool bFound = false;
- if ( curAttr == null )
- bFound = true; //the first namespace will be the one
- #if DEBUG
- if ( curAttr != null )
- Debug.Assert( curAttr.NamespaceURI == s_strReservedXmlns );
- #endif
- Debug.Assert( attrs!=null );
- int attrInd = attrs.Count;
- while ( attrInd > 0 ) {
- attrInd--;
- attr = attrs[attrInd];
- if ( bFound && attr.NamespaceURI == s_strReservedXmlns && !DuplicateNS( be, attr.LocalName ) ) {
- MoveTo(attr);
- return true;
- }
- if ( attr == curAttr )
- bFound = true;
- }
- }
- else {//defoliated so that we need to search through its column
- DataRow curRow = be.Row;
- if ( curRow == null )
- return false;
- //going through its attribute columns
- DataColumn curCol = PreviousColumn( curRow, col, true );
- while ( curCol != null ) {
- if ( curCol.Namespace == s_strReservedXmlns && !DuplicateNS( be, curCol.ColumnName ) ) {
- MoveTo( be, curCol, false );
- return true;
- }
- curCol = PreviousColumn( curRow, curCol, true );
- }
- }
- }
- return false;
- }
-
- //Caller( DataDocumentXPathNavigator will make sure that the node is at the right position for this call )
- internal bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToFirstNamespace(namespaceScope)");
- RealFoliate();
- _parentOfNS = this._node as XmlBoundElement;
- //only need to check with _node, even if _column is not null and its mapping type is element, it can't have attributes
- if ( _parentOfNS == null )
- return false;
- XmlNode node = this._node;
- XmlBoundElement be = null;
- while ( node != null ) {
- be = node as XmlBoundElement;
- if ( MoveToNextNamespace( be, null, null ) )
- return true;
- //didn't find it
- if ( namespaceScope == XPathNamespaceScope.Local )
- goto labelNoNS;
- //try the next element anccestor.
- do {
- node = node.ParentNode;
- } while ( node != null && node.NodeType != XmlNodeType.Element );
- }
- if ( namespaceScope == XPathNamespaceScope.All ) {
- MoveTo( this._doc.attrXml, null, false );
- return true;
- }
- labelNoNS:
- //didn't find one namespace node
- _parentOfNS = null;
- return false;
- }
- //endElem is on the path from startElem to root is enforced by the caller
- private bool DuplicateNS( XmlBoundElement endElem, string lname) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:DuplicateNS(endElem, lname)");
- if ( this._parentOfNS == null || endElem == null )
- return false;
- XmlBoundElement be = this._parentOfNS;
- XmlNode node = null;
- while ( be != null && be != endElem ) {
- if ( GetNamespace( be, lname ) != null )
- return true;
- node = (XmlNode)be;
- do {
- node = node.ParentNode;
- } while ( node != null && node.NodeType != XmlNodeType.Element );
- be = node as XmlBoundElement;
- }
- return false;
- }
-
- //Caller( DataDocumentXPathNavigator will make sure that the node is at the right position for this call )
- internal bool MoveToNextNamespace(XPathNamespaceScope namespaceScope) {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextNamespace(namespaceScope)");
- RealFoliate();
- Debug.Assert( _parentOfNS != null );
- XmlNode node = this._node;
- //first check within the same boundelement
- if ( this._column != null ) {
- Debug.Assert( this._column.Namespace == s_strReservedXmlns );
- if ( namespaceScope == XPathNamespaceScope.Local && _parentOfNS != this._node ) //already outside scope
- return false;
- XmlBoundElement be = this._node as XmlBoundElement;
- Debug.Assert( be != null );
- DataRow curRow = be.Row;
- Debug.Assert( curRow != null );
- DataColumn curCol = PreviousColumn( curRow, this._column, true );
- while ( curCol != null ) {
- if ( curCol.Namespace == s_strReservedXmlns ) {
- MoveTo( be, curCol, false );
- return true;
- }
- curCol = PreviousColumn( curRow, curCol, true );
- }
- //didn't find it in this loop
- if ( namespaceScope == XPathNamespaceScope.Local )
- return false;
- //try its ancesstor
- do {
- node = node.ParentNode;
- } while ( node != null && node.NodeType != XmlNodeType.Element );
- }
- else if ( this._node.NodeType == XmlNodeType.Attribute ) {
- XmlAttribute attr = (XmlAttribute)(this._node);
- Debug.Assert( attr != null );
- node = attr.OwnerElement;
- if ( node == null )
- return false;
- if ( namespaceScope == XPathNamespaceScope.Local && _parentOfNS != node ) //already outside scope
- return false;
- if ( MoveToNextNamespace( (XmlBoundElement)node, null, (XmlAttribute)attr ) )
- return true;
- //didn't find it
- if ( namespaceScope == XPathNamespaceScope.Local )
- return false;
- do {
- node = node.ParentNode;
- } while ( node != null && node.NodeType != XmlNodeType.Element );
- }
- // till now, node should be the next accesstor (bound) element of the element parent of current namespace node (attribute or data column)
- while ( node != null ) {
- //try the namespace attributes from the same element
- XmlBoundElement be = node as XmlBoundElement;
- if ( MoveToNextNamespace( be, null, null ) )
- return true;
- //no more namespace attribute under the same element
- do {
- node = node.ParentNode;
- } while ( node != null && node.NodeType == XmlNodeType.Element );
- }
- //didn't find the next namespace, thus return
- if ( namespaceScope == XPathNamespaceScope.All ) {
- MoveTo( this._doc.attrXml, null, false );
- return true;
- }
- return false;
- }
-
- [System.Diagnostics.Conditional("DEBUG")]
- private void AssertValid() {
- // This pointer must be int the document list
- //RealFoliate();
- this._doc.AssertPointerPresent( this );
- if ( this._column != null ) {
- // We must be on a de-foliated region
- XmlBoundElement rowElem = this._node as XmlBoundElement;
- Debug.Assert( rowElem != null );
- DataRow row = rowElem.Row;
- Debug.Assert( row != null );
- //ElementState state = rowElem.ElementState;
- //Debug.Assert( state == ElementState.Defoliated || _bNeedFoliated, "Region is accessed using column, but it's state is FOLIATED" );
- // We cannot be on a column for which the value is DBNull
- DataRowVersion rowVersion = ( row.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current;
- Debug.Assert( ! Convert.IsDBNull( row[ this._column, rowVersion ] ) );
- // If we are on the Text column, we should always have _fOnValue == true
- Debug.Assert( (this._column.ColumnMapping == MappingType.SimpleContent) ? (this._fOnValue == true) : true );
- }
- if ( this._column == null )
- Debug.Assert( !this._fOnValue );
- }
- internal XmlDataDocument Document { get { return _doc; } }
- bool IXmlDataVirtualNode.IsInUse() {
- //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:IsInUse()");
- return _owner.IsAlive;
- }
- }
- }
|