wasStitchNET – Blame information for rev 9

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/
8 office 7  
7 office 8 using System;
9 office 9 using System.Collections.Generic;
7 office 10 using System.Linq;
11 using System.Xml.Linq;
12  
13 namespace wasStitchNET.Patchers
14 {
15 public static class Utilities
16 {
9 office 17 public static IEnumerable<XElement> ParentsAndSelf(this XElement e)
18 {
19 if (e == null)
20 yield break;
21  
22 yield return e;
23  
24 foreach (var p in ParentsAndSelf(e.Parent))
25 {
26 yield return p;
27 }
28 }
29  
8 office 30 /// <summary>
31 /// Get the absolute XPath to a given XElement
32 /// (e.g. "/people/person[6]/name[1]/last[1]").
33 /// </summary>
34 /// <param name="element">
35 /// The element to get the index of.
36 /// </param>
7 office 37 public static string GetAbsoluteXPath(this XElement element)
38 {
39 if (element == null)
40 throw new ArgumentNullException("element");
41  
42 Func<XElement, string> relativeXPath = e =>
43 {
44 var index = e.IndexPosition();
45 var name = e.Name.LocalName;
46  
47 // If the element is the root, no index is required
48  
8 office 49 return index == -1
50 ? "/" + name
51 : string.Format
52 (
53 "/{0}[{1}]",
54 name,
55 index.ToString()
56 );
7 office 57 };
58  
59 var ancestors = from e in element.Ancestors()
8 office 60 select relativeXPath(e);
7 office 61  
62 return string.Concat(ancestors.Reverse().ToArray()) +
63 relativeXPath(element);
64 }
65  
8 office 66 /// <summary>
67 /// Get the index of the given XElement relative to its
68 /// siblings with identical names. If the given element is
69 /// the root, -1 is returned.
70 /// </summary>
71 /// <param name="element">
72 /// The element to get the index of.
73 /// </param>
7 office 74 public static int IndexPosition(this XElement element)
75 {
76 if (element == null)
77 throw new ArgumentNullException("element");
78  
79 if (element.Parent == null)
80 return -1;
81  
82 var i = 1; // Indexes for nodes start at 1, not 0
83  
84 foreach (var sibling in element.Parent.Elements(element.Name))
85 {
86 if (sibling == element)
87 return i;
88  
89 i++;
90 }
91  
92 throw new InvalidOperationException
93 ("element has been removed from its parent.");
94 }
95 }
8 office 96 }