2010-12-03 18 views

答えて

0

私はこれまでに作業しました。

注:これには、XPathNavigatorオブジェクトの基礎となるXmlDocumentが必要です。 XmlDocumentをラップしていないXPathNavigatorオブジェクトを持つことができます。そのような場合、これは機能しません。

これを呼び出すには、XPathNavigatorオブジェクトが現在存在することをXmlNodeに渡します。これはXPathNavigator.UnderlyingObjectに含まれています。

また、ネームスペースを明示的に設定した場合、キーが名前空間uriで、値がプレフィックスであるディクショナリを渡す必要があります。基本となるXmlDocumentは、元のXMLで定義されている名前空間を使用しますが、読み込んだ後に割り当てられた名前空間ではありません(理由は分かりません)。ネームスペースを明示的に設定していない場合、nullを渡すことができます。

完全なコードはXML Get Unique XPath

using System.Collections.Generic; 
using System.Text; 
using System.Xml; 

/// <summary> 

/// For an XmlNode in an XmlDocument, can determine the XPath 
///to return that specific node. Can also then determine the non-specific 

/// XPath to a subsequent child node (the XPath that will return that node AND ALSO any peer nodes of the same name(s)). 

/// </summary> 

public class NodeLocator 

{ 

    private NodeLocator next; 

    private readonly XmlNode node; 

    private readonly Dictionary<string, string> namespaceMap; 



    private NodeLocator(Dictionary<string, string> namespaceMap, XmlNode node) 

    { 

     this.node = node; 

     this.namespaceMap = namespaceMap ?? new Dictionary<string, string>(); 

    } 



    /// <summary> 

    /// Get the unique XPath for the passed in node. 

    /// </summary> 

    /// <param name="namespaceMap">If namespace prefixes are different from the raw XmlDocument, this dictionaru is key=uri, value=prefix.</param> 

    /// <param name="node">The node to get the unique XPath to.</param> 

    /// <returns>The unique XPath to node.</returns> 

    public static string GetUniqueLocation(Dictionary<string, string> namespaceMap, XmlNode node) 

    { 

     NodeLocator loc = new NodeLocator(namespaceMap, node); 

     while (node.ParentNode != null) 

     { 

      node = node.ParentNode; 

      if (node is XmlDocument) 

       break; 

      NodeLocator parentloc = new NodeLocator(namespaceMap, node); 

      parentloc.next = loc; 

      loc = parentloc; 

     } 

     return loc.Xpath(true); 

    } 



    /// <summary> 

    /// Get the unique XPath for the passed in node. It uses the unique XPath from the root to the parent and then non-unique XPath from the parent to the node. 

    /// </summary> 

    /// <param name="namespaceMap">If namespace prefixes are different from the raw XmlDocument, this dictionaru is key=uri, value=prefix.</param> 

    /// <param name="parent">The node to get the unique XPath to.</param> 

    /// <param name="node">The node to get the NON-unique XPath to.</param> 

    /// <returns>The unique XPath to node.</returns> 

    public static string GetLocation(Dictionary<string, string> namespaceMap, XmlNode parent, XmlNode node) 

    { 

     NodeLocator loc = new NodeLocator(namespaceMap, node); 

     while ((node.ParentNode != null) && (node.ParentNode != parent)) 

     { 

      node = node.ParentNode; 

      if (node is XmlDocument) 

       break; 

      NodeLocator parentloc = new NodeLocator(namespaceMap, node); 

      parentloc.next = loc; 

      loc = parentloc; 

     } 

     return loc.Xpath(false); 

    } 



    private string Xpath(bool unique) 

    { 

     StringBuilder sb = new StringBuilder(); 

     NodeLocator loc = this; 

     do 

     { 

      if (loc.node.Name.StartsWith("#")) 

      { 

       if (loc.node.Name == "#document") 

        sb.Append('/'); 

      } 

      else 

      { 

       sb.Append('/'); 

       if (loc.node is XmlAttribute) 

        sb.Append('@'); 

       sb.Append(FullName(loc.node)); 

       if (unique) 

       { 

        sb.Append('['); 

        sb.Append(loc.IndexInParent); 

        sb.Append(']'); 

       } 

      } 

      loc = loc.next; 

     } while (loc != null); 



     // no leading/for non-unique 

     if ((!unique) && (sb.Length > 0)) 

      sb.Remove(0, 1); 

     return sb.ToString(); 

    } 



    private string FullName(XmlNode _node) 

    { 

     if (string.IsNullOrEmpty(_node.NamespaceURI) || (!namespaceMap.ContainsKey(_node.NamespaceURI))) 

      return _node.Name; 

     return namespaceMap[_node.NamespaceURI] + ':' + _node.LocalName; 

    } 



    private int IndexInParent 

    { 

     get 

     { 

      int indexInParent = 1; 

      XmlNode parent = node.ParentNode; 

      string nodeName = FullName(node); 

      if (parent != null) 

      { 

       foreach (XmlNode child in parent.ChildNodes) 

       { 

        if (child == node) 

         break; 

        if (FullName(child) == nodeName) 

        { 

         indexInParent++; 

        } 

       } 

      } 

      return indexInParent; 

     } 

    } 

} 
にジッパーであります
関連する問題