wasStitchNET – Blame information for rev 7

Subversion Repositories:
Rev:
Rev Author Line No. Line
7 office 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 //
3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
4 // rights of fair usage, the disclaimer and warranty conditions. //
5 ///////////////////////////////////////////////////////////////////////////
6 // Based on: https://seattlesoftware.wordpress.com/2009/03/13/get-the-xpath-to-an-xml-element-xelement/
7 using System;
8 using System.Collections.Generic;
9 using System.Linq;
10 using System.Text;
11 using System.Reflection;
12 using System.Xml.Linq;
13  
14 namespace wasStitchNET.Patchers
15 {
16 public static class Utilities
17 {
18  
19 /// <summary>
20 /// Get the absolute XPath to a given XElement
21 /// (e.g. "/people/person[6]/name[1]/last[1]").
22 /// </summary>
23 /// <param name="element">
24 /// The element to get the index of.
25 /// </param>
26 public static string GetAbsoluteXPath(this XElement element)
27 {
28 if (element == null)
29 throw new ArgumentNullException("element");
30  
31 Func<XElement, string> relativeXPath = e =>
32 {
33 var index = e.IndexPosition();
34 var name = e.Name.LocalName;
35  
36 // If the element is the root, no index is required
37  
38 return (index == -1) ? "/" + name : string.Format
39 (
40 "/{0}[{1}]",
41 name,
42 index.ToString()
43 );
44 };
45  
46 var ancestors = from e in element.Ancestors()
47 select relativeXPath(e);
48  
49 return string.Concat(ancestors.Reverse().ToArray()) +
50 relativeXPath(element);
51 }
52  
53 /// <summary>
54 /// Get the index of the given XElement relative to its
55 /// siblings with identical names. If the given element is
56 /// the root, -1 is returned.
57 /// </summary>
58 /// <param name="element">
59 /// The element to get the index of.
60 /// </param>
61 public static int IndexPosition(this XElement element)
62 {
63 if (element == null)
64 {
65 throw new ArgumentNullException("element");
66 }
67  
68 if (element.Parent == null)
69 {
70 return -1;
71 }
72  
73 var i = 1; // Indexes for nodes start at 1, not 0
74  
75 foreach (var sibling in element.Parent.Elements(element.Name))
76 {
77 if (sibling == element)
78 {
79 return i;
80 }
81  
82 i++;
83 }
84  
85 throw new InvalidOperationException
86 ("element has been removed from its parent.");
87 }
88  
89 }
90 }