1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
// Copyright (c) Microsoft Corporation. All rights reserved.
//
using System;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Diagnostics;
using System.Collections.Generic;
namespace Microsoft.Ddue.Tools {
public static class BuildComponentUtilities {
// get the message strings from an exception
public static string GetExceptionMessage (Exception e) {
if (e == null) throw new ArgumentNullException("e");
string message = e.Message;
XmlException xmlE = e as XmlException;
if (xmlE != null) {
message = String.Format("{0} (LineNumber: {1}; LinePosition: {2}; SourceUri: '{3}')", message, xmlE.LineNumber, xmlE.LinePosition, xmlE.SourceUri);
}
XsltException xslE = e as XsltException;
if (xslE != null) {
message = String.Format("{0} (LineNumber: {1}; LinePosition: {2}; SourceUri: '{3}')", message, xslE.LineNumber, xslE.LinePosition, xslE.SourceUri);
}
if (e.InnerException != null) message = String.Format("{0} {1}", message, GetExceptionMessage(e.InnerException));
return (message);
}
// get InnerXml without changing the spacing
public static string GetInnerXml (XPathNavigator node) {
// check for null argument, and clone so we don't change input
if (node == null) throw new ArgumentNullException("node");
XPathNavigator current = node.Clone();
// create appropriate settings for the output writer
XmlWriterSettings settings = new XmlWriterSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.OmitXmlDeclaration = true;
// construct a writer for our output
StringBuilder builder = new StringBuilder();
XmlWriter writer = XmlWriter.Create(builder, settings);
// write the output
bool writing = current.MoveToFirstChild();
while (writing) {
current.WriteSubtree(writer);
writing = current.MoveToNext();
}
// finish up and return the result
writer.Close();
return(builder.ToString());
}
// get an array of nodes matching an XPath expression
public static XPathNavigator[] ConvertNodeIteratorToArray (XPathNodeIterator iterator) {
XPathNavigator[] result = new XPathNavigator[iterator.Count];
for (int i = 0; i < result.Length; i++) {
iterator.MoveNext();
result[i] = iterator.Current.Clone();
// clone is required or all entries will equal Current!
}
return(result);
}
/// <summary>
/// Returns the string result from evaluating an xpath expression against the given document and context.
/// </summary>
public static string EvalXPathExpr(IXPathNavigable doc, XPathExpression xpe, CustomContext c) {
XPathExpression t = xpe.Clone();
t.SetContext(c);
return doc.CreateNavigator().Evaluate(t).ToString();
}
/// <summary>
/// Returns the string result from evaluating an xpath expression against the given document and
/// context created from key/value pairs.
/// </summary>
/// <example>
/// string result = BuildComponentUtilities.EvalXPathExpr(doc, "concat($key, '.htm')", "key", "file");
/// </example>
public static string EvalXPathExpr(IXPathNavigable doc, XPathExpression xpe, params string[] keyValuePairs) {
Debug.Assert(keyValuePairs.Length % 2 == 0);
CustomContext cc = new CustomContext();
for (int i = 0; i < keyValuePairs.Length; i += 2)
cc[keyValuePairs[i]] = keyValuePairs[i + 1];
return EvalXPathExpr(doc, xpe, cc);
}
/// <summary>
/// Returns the path argument adjusted to be relative to the base path. Absolute path names will
/// be returned unchanged.
/// </summary>
/// <example>
/// path: "xxx/aaa/target.html"
/// basePath: "xxx/bbb/source.html"
/// result: "../aaa/target.html"
/// </example>
public static string GetRelativePath(string path, string basePath) {
// ignore absolute path names and an empty basePath
if (!string.IsNullOrEmpty(path) && path[0] != '/' && !string.IsNullOrEmpty(basePath)) {
List<string> pathParts = new List<string>(path.Split('/'));
List<string> basePathParts = new List<string>(basePath.Split('/'));
// remove the base path file name
if (basePathParts.Count > 0)
basePathParts.RemoveAt(basePathParts.Count - 1);
// strip common base path bits
while (pathParts.Count > 0 && basePathParts.Count > 0 &&
string.Equals(pathParts[0], basePathParts[0], StringComparison.CurrentCultureIgnoreCase)) {
pathParts.RemoveAt(0);
basePathParts.RemoveAt(0);
}
// move up one level for each remaining base path part
foreach (string s in basePathParts)
pathParts.Insert(0, "..");
path = string.Join("/", pathParts.ToArray());
}
return path;
}
}
}
|