PathDescriptorParser.cs
上传用户:hbhltzc
上传日期:2022-06-04
资源大小:1925k
文件大小:9k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. //------------------------------------------------------------------------------
  2. // <copyright file="PathDescriptorParser.cs" company="Microsoft">
  3. //     Copyright (c) Microsoft Corporation.  All rights reserved.
  4. // </copyright>                                                                
  5. //------------------------------------------------------------------------------
  6. using System;
  7. using System.Xml;
  8. using System.Diagnostics;
  9. using System.Collections;
  10. namespace Microsoft.XmlDiffPatch
  11. {
  12. internal class PathDescriptorParser
  13. {
  14.         static char[] Delimiters = new char[] {'|','-','/'};
  15.         static char[] MultiNodesDelimiters = new char[] {'|','-'};
  16.         internal static XmlNodeList SelectNodes( XmlNode rootNode, XmlNode currentParentNode, string pathDescriptor )
  17.         {
  18.             switch ( pathDescriptor[0] )
  19.             {
  20.                 case '/':
  21.                     return SelectAbsoluteNodes( rootNode, pathDescriptor );
  22.                 case '@':
  23.                     if ( pathDescriptor.Length < 2 )
  24.                         OnInvalidExpression( pathDescriptor );
  25.                     if ( pathDescriptor[1] == '*' )
  26.                         return SelectAllAttributes( currentParentNode );
  27.                     else
  28.                         return SelectAttributes( currentParentNode, pathDescriptor );
  29.                 case '*':
  30.                     if ( pathDescriptor.Length == 1 )
  31.                         return SelectAllChildren( currentParentNode );
  32.                     else 
  33.                     {
  34.                         OnInvalidExpression( pathDescriptor );
  35.                         return null;
  36.                     }
  37.                 default:
  38.                     return SelectChildNodes( currentParentNode, pathDescriptor, 0 );
  39.             }
  40.         }
  41.         private static XmlNodeList SelectAbsoluteNodes( XmlNode rootNode, string path )
  42.         {
  43.             Debug.Assert( path[0] == '/' );
  44.             
  45.             int pos = 1;
  46.             XmlNode node = rootNode;
  47.             for (;;)
  48.             {
  49.                 int startPos = pos;
  50.                 XmlNodeList childNodes = node.ChildNodes;
  51.                 int nodePos = ReadPosition( path, ref pos );
  52.                 
  53.                 if ( pos == path.Length || path[pos] == '/' ) {
  54.                     if ( childNodes.Count == 0 || nodePos < 0 || nodePos > childNodes.Count )
  55.                         OnNoMatchingNode( path );
  56.                     node = childNodes.Item( nodePos - 1 );
  57.                     if ( pos == path.Length ) {
  58.                         XmlPatchNodeList list = new SingleNodeList();
  59.                         list.AddNode( node );
  60.                         return list;
  61.                     }
  62.                     pos++;
  63.                 }
  64.                 else {
  65.                     if ( path[pos] == '-' || path[pos] == '|' ) {
  66.                         return SelectChildNodes( node, path, startPos );
  67.                     }
  68.                     OnInvalidExpression( path );
  69.                 }
  70.             }
  71.         }
  72.         private static XmlNodeList SelectAllAttributes( XmlNode parentNode )
  73.         {
  74.             XmlAttributeCollection attributes = parentNode.Attributes;
  75.             if ( attributes.Count == 0 ) 
  76.             {
  77.                 OnNoMatchingNode( "@*" );
  78.                 return null;
  79.             }
  80.             else if ( attributes.Count == 1 ) 
  81.             {
  82.                 XmlPatchNodeList nodeList = new SingleNodeList();
  83.                 nodeList.AddNode( attributes.Item( 0 ) );
  84.                 return nodeList;
  85.             }
  86.             else 
  87.             {
  88.                 IEnumerator enumerator = attributes.GetEnumerator();
  89.                 XmlPatchNodeList nodeList = new MultiNodeList();
  90.                 while ( enumerator.MoveNext() )
  91.                     nodeList.AddNode( (XmlNode) enumerator.Current );
  92.                 return nodeList;
  93.             }
  94.         }
  95.         private static XmlNodeList SelectAttributes( XmlNode parentNode, string path )
  96.         {
  97.             Debug.Assert( path[0] == '@' );
  98.             int pos = 1;
  99.             XmlAttributeCollection attributes = parentNode.Attributes;
  100.             XmlPatchNodeList nodeList = null;
  101.             for (;;) 
  102.             {
  103.                 string name = ReadAttrName( path, ref pos );
  104.                 if ( nodeList == null ) 
  105.                 {
  106.                     if ( pos == path.Length ) 
  107.                         nodeList = new SingleNodeList();
  108.                     else
  109.                         nodeList = new MultiNodeList();
  110.                 }
  111.                 XmlNode attr = attributes.GetNamedItem( name );
  112.                 if ( attr == null )
  113.                     OnNoMatchingNode( path );
  114.                 nodeList.AddNode( attr );
  115.                 if ( pos == path.Length )
  116.                     break;
  117.                 else if ( path[pos] == '|' ) {
  118.                     pos++;
  119.                     if ( path[pos] != '@' )
  120.                         OnInvalidExpression( path );
  121.                     pos++;
  122.                 }
  123.                 else
  124.                     OnInvalidExpression( path );
  125.             }
  126.             return nodeList;
  127.         }
  128.         private static XmlNodeList SelectAllChildren( XmlNode parentNode )
  129.         {
  130.             XmlNodeList children = parentNode.ChildNodes;
  131.             if ( children.Count == 0 ) 
  132.             {
  133.                 OnNoMatchingNode( "*" );
  134.                 return null;
  135.             }
  136.             else if ( children.Count == 1 ) 
  137.             {
  138.                 XmlPatchNodeList nodeList = new SingleNodeList();
  139.                 nodeList.AddNode( children.Item( 0 ) );
  140.                 return nodeList;
  141.             }
  142.             else 
  143.             {
  144.                 IEnumerator enumerator = children.GetEnumerator();
  145.                 XmlPatchNodeList nodeList = new MultiNodeList();
  146.                 while ( enumerator.MoveNext() )
  147.                     nodeList.AddNode( (XmlNode) enumerator.Current );
  148.                 return nodeList;
  149.             }   
  150.         }
  151.         private static XmlNodeList SelectChildNodes( XmlNode parentNode, string path, int startPos )
  152.         {
  153.             int pos = startPos;
  154.             XmlPatchNodeList nodeList = null;
  155.             XmlNodeList children = parentNode.ChildNodes;
  156.             int nodePos = ReadPosition( path, ref pos );
  157.             if ( pos == path.Length ) 
  158.                 nodeList = new SingleNodeList();
  159.             else
  160.                 nodeList = new MultiNodeList();
  161.             for (;;)
  162.             {
  163.                 if ( nodePos <= 0 || nodePos > children.Count )
  164.                     OnNoMatchingNode( path );
  165.                 XmlNode node = children.Item( nodePos - 1 );
  166.                 nodeList.AddNode( node );
  167.                 if ( pos == path.Length )
  168.                     break;
  169.                 else if ( path[pos] == '|' )
  170.                     pos++;
  171.                 else if ( path[pos] == '-' )
  172.                 {
  173.                     pos++;
  174.                     int endNodePos = ReadPosition( path, ref pos );
  175.                     if ( endNodePos <= 0 || endNodePos > children.Count )
  176.                         OnNoMatchingNode( path );
  177.                     while ( nodePos < endNodePos )
  178.                     {
  179.                         nodePos++;
  180.                         node = node.NextSibling;
  181.                         nodeList.AddNode( node );
  182.                     }
  183.                     Debug.Assert( (object)node == (object)children.Item( endNodePos - 1 ) );
  184.                     if ( pos == path.Length )
  185.                         break;
  186.                     else if ( path[pos] == '|' )
  187.                         pos++;
  188.                     else 
  189.                         OnInvalidExpression( path );
  190.                 }
  191.                 nodePos = ReadPosition( path, ref pos );
  192.             }
  193.             return nodeList;
  194.         }
  195.         private static int ReadPosition( string str, ref int pos ) 
  196.         {
  197.             int end = str.IndexOfAny( Delimiters, pos );
  198.             if ( end < 0 )
  199.                 end = str.Length;
  200.             
  201.             // TODO: better error handling if this should be shipped
  202.             int nodePos = int.Parse( str.Substring( pos, end - pos ) );
  203.             pos = end;
  204.             return nodePos;
  205.         }
  206.         private static string ReadAttrName( string str, ref int pos ) 
  207.         {
  208.             int end = str.IndexOf( '|', pos );
  209.             if ( end < 0 )
  210.                 end = str.Length;
  211.             
  212.             // TODO: better error handling if this should be shipped
  213.             string name = str.Substring( pos, end - pos );
  214.             pos = end;
  215.             return name;
  216.         }
  217.         private static void OnInvalidExpression( string path )
  218.         {
  219.             XmlPatchError.Error( XmlPatchError.InvalidPathDescriptor, path );
  220.         }
  221.         private static void OnNoMatchingNode( string path )
  222.         {
  223.             XmlPatchError.Error( XmlPatchError.NoMatchingNode, path );
  224.         }
  225. }
  226. }