次の方法で共有


異なるストアに対する XPathNavigator

XPathNavigator は、IXPathNavigable インターフェイスを実装するストアに対する XPath クエリの実行に役立ちます。IXPathNavigable インターフェイスを実装するクラスは、XPathDocumentXmlDocument、および XmlDataDocument です。

XPathDocument クラスを使用すると、XML のストリームに対する XPath クエリを実行できます。これは、XPath クエリおよび XSLT 変換を実行するために高度な最適化が行われています。このクラスは、XPath のパフォーマンスの優先順位が最も高い場合、XSLT 変換用として望ましいクラスです。

XmlDocument クラスは、XML の編集可能な DOM ビューの提供に加えて、データに対する XPath を可能にします。同じ XML に対するクエリの結果という観点では、XPathDocument および XmlDocument は同様に動作します。XmlDocument クラスは編集機能を備えているため、XPathDocument に比べて XPath クエリのパフォーマンスが劣ります。

XmlDataDocument クラスは、Dataset と同期化された完全に準拠した DOM を提供します。XmlDocument クラスを継承し、リレーショナル データの階層化 XML ビューを取得するために使用されます。Dataset に格納されているデータの XML 表現に対して XPath クエリを実行するために使用することもできます。XmlDataDocument の詳細については、「Dataset と XmlDataDocument の同期」を参照してください。

これらのクラスで XPath クエリを実行するには、CreateNavigator 関数を呼び出して XPathNavigator を返します。次に、このセクションでこれから説明するように、XPathNavigator を使用してドキュメントに対して XPath クエリを実行できます。

独自のナビゲータを定義するために、XPathNavigator クラスを拡張することもできます。そのためには、仮想ノード構造の作成とこの構造をナビゲートするメソッドの実装が必要です。このノード構造を記述すると、XPath クエリを実行する機能が有効になります。XPathNavigator クラスの Select メソッドが実装され、この構造を機能させるだけです。ファイル システムに XPathNavigator を実装する例を下に示します。

仮想ノード構造の作成から開始します。これは、元になるファイル システムを公開して XML Infoset のすべての情報を格納する構造です。この XML 構造は、ノードに関する情報を返す XPathNavigator クラスのメソッドをオーバーライドすることによって公開されます。この例では、ディレクトリおよびファイルが要素として公開されます。ファイル システムのツリー構造は、公開された XML Infoset のツリー構造にミラー化されます。ディレクトリを表す要素は、ディレクトリのローカル名と作成時間を属性として備えます。ファイルを表す要素は、ローカル名、作成時間、ファイル長を属性として備えます。このファイル システムに対して、/abc/xml のようにクエリを実行できます。このクエリでは、ローカル名 abc を持つディレクトリに格納されている、ローカル名 xml を持つすべてのディレクトリまたはファイルを選択します。

この構造を公開するために、次のノード プロパティをオーバーライドする必要があります。

  • NodeType
  • LocalName
  • Name
  • Prefix
  • Value
  • BaseURI
  • IsEmptyElement
  • XmlLang
  • NameTable

この構造を公開するには、次の属性アクセサをオーバーライドする必要があります。

  • HasAttributes
  • GetAttributes
  • MoveToAttributes
  • MoveToFirstAttributes
  • MoveToNextAttributes

この構造を公開するには、次の名前空間アクセサをオーバーライドする必要があります。

  • GetNamespace
  • MoveToNamespace
  • MoveToFirstNamespace
  • MoveToNextNamespace

これらのメソッドおよびプロパティを使用して、元になる構造を XML Infoset として完全に公開できます。

さらに、NameTable プロパティから提供される LocalNameNameSpaceUriPrefix の各文字列を NameTable に追加する必要があります。LocalNameNamespaceURIPrefix の各プロパティが返されるときは、文字列は NameTable から返されます。名前間の比較は、速度が遅い文字列比較ではなく、オブジェクト比較によって実行されます。

さらに、この仮想ノード構造をナビゲートするメソッドも実装する必要があります。このようなメソッドを次に示します。

  • MoveToNext
  • MoveToPrevious
  • MoveToFirst
  • MoveToFirstChild
  • MoveToParent
  • MoveToRoot
  • MoveTo
  • MoveToId
  • IsSamePosition
  • HasChildren

これらのメソッドは元になる構造をツリーとして公開します。これらのメソッドとプロパティを実装すると、この仮想ノード セットに対して XPath クエリが機能します。たとえば、次に示すコードでは、ハード ドライブのディレクトリを移動するカスタム XPathNavigator を作成します。移動の開始点は C:\Program Files で、ファイルとフォルダを再帰的に検索していきます。そのため、マシンによっては、コンソールへの出力が大量になります。開始点は、ハード ドライブ上にある任意のフォルダに変更できます。

using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;

public class Sample {
    static FileSystemNavigator fsn;
    public static void Main() {
        // This is the hard code for C:\ProgramFiles. You can modify this 
        // to point to a folder on your own machine for test purposes.
        fsn = new FileSystemNavigator(@"C:\Program Files");

        if (fsn.MoveToFirstChild()) {
            ShowNavigator(String.Empty);
        }
    }
    public static void ShowNavigator(string indent) {
        do {
            Console.WriteLine("{0}Name: {1}", indent, fsn.Name);
            if (fsn.HasChildren) {
                fsn.MoveToFirstChild();
                ShowNavigator(indent + "  ");
                fsn.MoveToParent();
            }
        } while (fsn.MoveToNext());
    }
}

public class FileSystemNavigator: XPathNavigator 
    {
      static int[]      NumberOfAttributes = { 2, 3 };
      //The NodeTypes used.
      public enum NodeTypes { Root, Element,  Attribute, Text };

      internal NavigatorState state;
      //Attribute names: For example a type 1 element will have a type 2 attribute named "Length"
      static String[][] AttributeIds       = new String[2][] 
               {
                  new String[] {"Name", "CreationTime"},   
                  new String[] {"Name", "CreationTime", "Length"}  
                };
      NameTable nametable;
      public FileSystemNavigator( String rootNode ) 
      {
          FileSystemInfo document = Directory.CreateDirectory(rootNode);
          nametable = new NameTable();
          nametable.Add(String.Empty);
          //if the Directory does not exist then rootNode must be a file.
          if( !document.Exists )
          {
            //create the file if it does not already exists
            FileStream tempStream = File.Open(rootNode,System.IO.FileMode.OpenOrCreate);
            tempStream.Close();
            document = new FileInfo(rootNode);
       }

         if( document.Exists )
         {
            state = new NavigatorState(document);

         }
         else
         {
            throw (new Exception("Root node must be a directory or a file"));
         }
      }
   
      public FileSystemNavigator( FileSystemInfo document ) 
      {
         nametable = new NameTable();
         nametable.Add(String.Empty);
         if( document.Exists )
         {
                state = new NavigatorState(document);
         
         }
         else
         {
             throw (new Exception("Root node must be a directory or a file"));
         }
         }

    public FileSystemNavigator( FileSystemNavigator navigator ) 
         {
         state = new NavigatorState(navigator.state);
         nametable = (NameTable)navigator.NameTable;
     
     }

       public override XPathNavigator Clone() 
       {
       return new FileSystemNavigator(this);
    }

       //NodeProperties
       public override XPathNodeType NodeType 
    { 
       get 
       {
       switch (state.Node) 
          {
             case NodeTypes.Root :
                 return XPathNodeType.Root;
              case NodeTypes.Element :
                   return XPathNodeType.Element;
              case NodeTypes.Attribute :
                  return XPathNodeType.Attribute;
              case NodeTypes.Text :
                  return XPathNodeType.Text;
           }
           return XPathNodeType.All;
           }
     }
     public override string LocalName 
     {
         
         get 
         {
             nametable.Add(Name);
             return nametable.Get(Name); 
         }
     }

     public override string Name 
       { 
         get 
           { 
             switch (state.Node)
           {
             case NodeTypes.Text :
                  return state.TextValue;
              case NodeTypes.Attribute :
                  return state.AttributeText;
              case NodeTypes.Element :
                   return state.ElementText;
               default :
                   return String.Empty;
                   
            }
        }
     }
     public override string NamespaceURI 
       {
        get 
        {
              return nametable.Get(String.Empty); 
           }
      }
      
      public override string Prefix 
       {
          get { return nametable.Get(String.Empty); }
       }
         public override string Value
      {
          get { 
               return state.TextValue;
                }
      }
      public override String BaseURI 
      {
          get { return String.Empty; } 
      }
      public override bool IsEmptyElement
      {
          get 
         {
             if(state.ElementType == 1) 
                return true;
           else 
               return false;
      }
      }
      
      public override string XmlLang
      {
         get{return "en-us";}
      }
      
      public override XmlNameTable NameTable 
      {
        get 
         { 
            return nametable; 
        }
      }
  
//Attribute Accessors

      public override bool HasAttributes 
      {
         get
         {
             if((state.Node != NodeTypes.Root) && (state.Node != NodeTypes.Attribute) && (state.Node != NodeTypes.Text))
                 return true;
             else
               return false;
      }
      }
      public override string GetAttribute( string localName, string namespaceURI ) 
        {
            if( HasAttributes)
            {
                int i;
                for(i = 0; i <  NumberOfAttributes[state.ElementType]; i++)
                {
                    if( AttributeIds[state.ElementType][i] == localName )
                        break;
                }

                if( i < NumberOfAttributes[state.ElementType] )
                {
                int TempAttribute = state.Attribute;
                NodeTypes TempNodeType  = state.Node;
                state.Attribute = i;
                state.Node = NodeTypes.Attribute;
                String AttributeValue = state.TextValue;
                state.Node =  TempNodeType;
                state.Attribute = TempAttribute;
                return AttributeValue;
                }
            }
            return String.Empty;
        }

        public override bool MoveToAttribute( string localName, string namespaceURI ) 
        {
            if( state.Node == NodeTypes.Attribute )
                MoveToElement();
            if( state.Node == NodeTypes.Element )
            {
                int i;
                for(i = 0; i < AttributeCount; i++)
                    if( AttributeIds[state.ElementType][i] == localName )
                    {
                        state.Attribute = i;
                        state.Node      = NodeTypes.Attribute;
                        return true;
                    }
            }
            return false;
        }

        public override bool MoveToFirstAttribute() 
        {
            if( state.Node == NodeTypes.Attribute )
                MoveToElement();
            if( AttributeCount > 0 )
            {
                state.Attribute = 0;
                state.Node = NodeTypes.Attribute;
                return true;
            }
            return false;
        }
        public override bool MoveToNextAttribute() 
        {
            
            int TempAttribute = -1;
            if( state.Node == NodeTypes.Attribute )
            {
                TempAttribute = state.Attribute;
                MoveToElement();
            }
            if( (TempAttribute + 1) < AttributeCount )
            {
                state.Attribute = TempAttribute + 1;
                state.Node = NodeTypes.Attribute;
                return true;
            }
            state.Node = NodeTypes.Attribute;
            state.Attribute = TempAttribute;
            return false;
        }

        //Namespace Accesors
        public override string GetNamespace(string localname)
        {
            return String.Empty;
        }
        public override bool MoveToNamespace(string Namespace)
        {
            return false;
        }

        public override bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope)
        {
            return false;
        }

        public override bool MoveToNextNamespace(XPathNamespaceScope namespaceScope)
        {
            return false;
        }
        
//Tree Navigation
    
        public override bool MoveToNext() 
        {
            int NextElement = IndexInParent + 1;
            FileSystemNavigator TempState = (FileSystemNavigator) this.Clone();
            if ( MoveToParent() )
            {
                if( MoveToChild(NextElement) )
                    return true;
            }
            this.state = new NavigatorState(TempState.state);
            return false;
        }
        
        public override bool MoveToPrevious() 
        {
            int NextElement = IndexInParent - 1;
            FileSystemNavigator TempState = (FileSystemNavigator) this.Clone();
            if ( MoveToParent() )
            {
                if( MoveToChild(NextElement) )
                    return true;
            }
            this.state = new NavigatorState(TempState.state);
            return false;
        }

        public override bool MoveToFirst() 
        {
            FileSystemNavigator TempState = (FileSystemNavigator) this.Clone();
            if ( MoveToParent() )
            {
                if( MoveToChild(0) )
                    return true;
            }
            this.state = new NavigatorState(TempState.state);
            return false;

        }
        public override bool MoveToFirstChild() 
        {
            FileSystemNavigator TempState = (FileSystemNavigator) this.Clone();
            if( MoveToChild(0) )
                return true;
            this.state = new NavigatorState(TempState.state);
            return false;
        }
    
        public override bool MoveToParent() 
        {
            switch(state.Node)
            {
                case NodeTypes.Root: 
                    return false;
                default:
                    if( state.Root != state.Doc.FullName )
                    {
                        if( state.Doc is DirectoryInfo )
                            state.Doc = ((DirectoryInfo) state.Doc).Parent;
                        else if( state.Doc is FileInfo )
                            state.Doc = ((FileInfo) state.Doc).Directory;
                        state.Node = NodeTypes.Element;
                        state.Attribute = -1;
                        state.ElementType = 0;
                        if( state.Root != state.Doc.FullName )
                        {
                            FileSystemInfo[] FileSystemEnumerator = ( ((DirectoryInfo) state.Doc).Parent).GetFileSystemInfos();
                            for(int i = 0; i < FileSystemEnumerator.Length; i++ )
                        {
                                if( FileSystemEnumerator[i].Name == state.Doc.Name )
                                {
                                state.ElementIndex = i;
                                }
                            }
                        }
                        else
                        {
                            state.ElementIndex = 0;
                        }
                        return true;
                    }
                    else
                    {
                        MoveToRoot();
                        return true;
                    }

        
            }
        }


        public override void MoveToRoot()
        {
            state.Node=NodeTypes.Root;
            state.Doc    = new FileInfo(state.Root);
            state.Attribute    = -1;
            state.ElementType  = -1;
            state.ElementIndex = -1;
        }
        public override bool MoveTo( XPathNavigator other ) 
        {
            if( other is FileSystemNavigator )
            {
                this.state = new NavigatorState( ((FileSystemNavigator) other).state);
                return true;
            }
            return false;
            }
        public override bool MoveToId( string id ) 
        {
            return false;
        }


        public override bool IsSamePosition( XPathNavigator other ) 
        {
            if( other is FileSystemNavigator )
            {
                if( state.Node == NodeTypes.Root )
                {
                    return (((FileSystemNavigator) other).state.Node == NodeTypes.Root);
                }
                else
                {
                    return (state.Doc.FullName == ((FileSystemNavigator) other).state.Doc.FullName);
                }
            }
            return false;
    
        
        }
    
        public override bool HasChildren 
        {
            get 
            { 
                return (ChildCount > 0); 
            }
        }
        


/***************Helper Methods*****************************************/
    
        //This is a helper method. Move the XPathNavigator from an attribute 
      // to its associated element.
        public bool MoveToElement() 
        {
            state.Attribute = -1;
            state.Node      = NodeTypes.Element;
            if ( state.Doc is DirectoryInfo )
                state.ElementType = 0;
            else 
                state.ElementType = 1;
            return true;
        }
        //Gets the index of this node if it is an element or the index of
      // the element node associated with the attribute.
        public int IndexInParent 
        {
            get 
            { 
                return state.ElementIndex; 
            }
        }
    

        
        //Helper method. Move to child i of the current node.
        public bool MoveToChild( int i ) 
        {
            if( i >= 0 )
            {
                    if( state.Node == NodeTypes.Root && i == 0)
                {
                    state.Doc = Directory.CreateDirectory(state.Root);
                    state.ElementType = 0;
                    if( !state.Doc.Exists )
                    {
                        FileStream tempStream = File.Open(state.Root,System.IO.FileMode.OpenOrCreate);
                        tempStream.Close();
                        state.Doc = new FileInfo(state.Root);
                        state.ElementType = 1;

                    }
                    state.Node = NodeTypes.Element;
                    state.Attribute = -1;
                    state.ElementIndex = 0;
                    return true;
                }
                else if( state.Node == NodeTypes.Element && state.ElementType == 0 )
                {
                
                    FileSystemInfo[] DirectoryEnumerator = ( (DirectoryInfo) state.Doc).GetFileSystemInfos();
                
                    if( i < DirectoryEnumerator.Length )
                    {
                        state.Node = NodeTypes.Element;
                        state.Attribute = -1;
                        state.ElementIndex = i;
                        if( DirectoryEnumerator[i] is DirectoryInfo)
                        {
                                state.Doc = DirectoryEnumerator[i];
                                state.ElementType = 0;
                        }
                        else if( DirectoryEnumerator[i] is FileInfo)
                        {
                            state.Doc = DirectoryEnumerator[i];
                            state.ElementType = 1;
                        }
                        return true;
                    }
                }
            }
            return false;
        }
        
        //returns the number of attributes that the current node has
        public int AttributeCount 
        {
            get 
            { 
                if( state.Node != NodeTypes.Root )
                {
                    return NumberOfAttributes[state.ElementType];
                }
                return 0;
            }
        }
        //Helper method. Returns the number of children that the current node has.
        public int ChildCount 
        {
            get 
            { 
                switch(state.Node)
                {
                    case NodeTypes.Root: 
                        return 1;
                    case NodeTypes.Element:
                        if( state.ElementType == 0 )
                        {
                            return (((DirectoryInfo) state.Doc).GetFileSystemInfos()).Length;
                        }
                        return 0;
                    default:
                        return 0;
                }
            }
        }
    
        //This class keeps track of the state the navigator is in.
        internal class NavigatorState
        {
            //Represents the element that the navigator is currently at.
            public FileSystemInfo doc;
            //The directory or file at the top of the tree
            String root;
            //The type of attribute that the current node is. -1 if the
         // navigator is not currently positioned on an attribute.
            public int attribute;
            //elementType of 0 is a directory and elementType of 1 is a file
            public int elementType;
            public int elementIndex;
            //The type of the current node
            public NodeTypes node;

            public NavigatorState(FileSystemInfo document)
            {
                Doc          = document;
                Root         = doc.FullName;
                Node         = NodeTypes.Root;
                Attribute    = -1;
                ElementType  = -1;
                ElementIndex = -1;
        
            }

            public NavigatorState(NavigatorState NavState)
            {
                Doc          = NavState.Doc;
                Root         = NavState.Root;
                Node         = NavState.Node;
                Attribute    = NavState.Attribute;
                ElementType  = NavState.ElementType;
                ElementIndex = NavState.ElementIndex;
        
            }

            public FileSystemInfo Doc
            {
                get 
                {
                    return doc;
                }
                set 
                {
                    doc = value;
                }
            }
    
            public String Root
            {
                get 
                {
                    return root;
                }
                set 
                {
                    root = value;
                }
            }

            public int Attribute
            {
                get 
                {
                    return attribute;
                }
                set 
                {
                    attribute = value;
                }
            }

            public int ElementType
            {
                get 
                {
                    return elementType;
                }
                set 
                {
                    elementType = value;
                }
            }

            public int ElementIndex
            {
                get 
                {
                    return elementIndex;
                }
                set 
                {
                    elementIndex = value;
                }
            }


            public NodeTypes Node
            {
                get 
                {
                    return node;
                }
                set 
                {
                    node = value;
                }
            }
            //Returns the TextValue of the current node
            public String TextValue
            {
                get 
                {
                    switch(Node)
                    {
                        case NodeTypes.Root :
                            return null;
                        case NodeTypes.Element : 
                            return null;
                        case NodeTypes.Attribute :
                            if( ElementType == 0 )
                            {
                                DirectoryInfo dInfo = (DirectoryInfo ) Doc;
                                switch(Attribute)
                                {
                                        case 0: return dInfo.Name;
                                        case 1: return dInfo.CreationTime.ToString();    
                                    }
                                }
                            else if( ElementType == 1 )
                            {
                                FileInfo fInfo = (FileInfo ) Doc;
                                switch(Attribute)
                                {
                                    case 0: return fInfo.Name;
                                    case 1: return (String) fInfo.CreationTime.ToString();
                                    case 2: return (String) fInfo.Length.ToString();
                                }
                            }
                            break;
                        case NodeTypes.Text :
                            return null;
                    }
                    return null;
                }
            }
            //returns the value of the attribute
            public String AttributeText
            {
                get 
                {
                    if( Node == NodeTypes.Attribute )
                        return AttributeIds[ElementType][Attribute];
                    return null;
                }
            }
            //Returns the name of the element.
            public String ElementText
            {
                get 
                {
                    return doc.Name;
                }
            }

        }
    }

参照

.NET Framework の XPathNavigator