1 using System;
2 using System.IO;
3 using System.Text;
4 using System.Dom;
5 using System.XPath;
6
7 public string Version()
8 {
9 return "2.0.0";
10 }
11
12 void PrintHelp()
13 {
14 Console.WriteLine("XPath Query Debugger version " + Version());
15 Console.WriteLine("Usage: xpq [options] \"<XPath query>\" <xmlFileName>");
16 Console.WriteLine("Compiles given XPath query, executes it on given <xmlFileName> and prints the query and results as XML.");
17 Console.WriteLine("Options:");
18 Console.WriteLine("--help | -h");
19 Console.WriteLine(" Print this help.");
20 Console.WriteLine("--verbose | -v");
21 Console.WriteLine(" Be verbose.");
22 Console.WriteLine("--debug-parsing | -p");
23 Console.WriteLine(" Print parsing query expression to stdout.");
24 }
25
26 void Execute(const string& xpathQuery, const string& xmlFilePath, Duration& parsingDuration, bool verbose)
27 {
28 if (verbose)
29 {
30 Console.WriteLine("> " + xmlFilePath);
31 }
32 TimePoint startParsing = Now();
33 UniquePtr<Document> document = ReadDocument(xmlFilePath);
34 TimePoint endParsing = Now();
35 parsingDuration = endParsing - startParsing;
36 if (verbose)
37 {
38 Console.WriteLine("> " + xpathQuery);
39 }
40 UniquePtr<XPathObject> evaluationResult = Evaluate(ToUtf32(xpathQuery), document.Get());
41 UniquePtr<Node> evaluationDom;
42 if (!evaluationResult.IsNull())
43 {
44 evaluationDom = evaluationResult->ToDom();
45 }
46 UniquePtr<Document> result(new Document());
47 result->AppendChild(UniquePtr<Node>(new Element(u"xpath")));
48 Element* queryElement = new Element(u"query");
49 result->DocumentElement()->AppendChild(UniquePtr<Node>(queryElement));
50 UniquePtr<Node> queryNode = GetXPathQueryDom();
51 if (!queryNode.IsNull())
52 {
53 queryElement->AppendChild(Rvalue(queryNode));
54 }
55 Element* resultElement = new Element(u"result");
56 result->DocumentElement()->AppendChild(UniquePtr<Node>(resultElement));
57 if (!evaluationDom.IsNull())
58 {
59 resultElement->AppendChild(Rvalue(evaluationDom));
60 }
61 CodeFormatter formatter(Console.Out());
62 formatter.SetIndentSize(2);
63 result->Write(formatter);
64 }
65
66 void Run(int n, const string& query, const string& xmlFilePath, bool verbose)
67 {
68 TimePoint start = Now();
69 Duration parsingDuration;
70 Execute(query, xmlFilePath, parsingDuration, verbose);
71 TimePoint end = Now();
72 Duration duration = end - start;
73 Console.WriteLine("execution number: " + ToString(n));
74 Console.WriteLine("parsing XML took " + DurationStr(parsingDuration));
75 Console.WriteLine("parsing XPath query took " + DurationStr(XPathQueryDuration()));
76 Console.WriteLine("evaluating XPath query took " + DurationStr(XPathExecuteDuration()));
77 Console.WriteLine("total duration: " + DurationStr(duration));
78 }
79
80 int main(int argc, const char** argv)
81 {
82 try
83 {
84 bool first = true;
85 bool verbose = false;
86 string query;
87 string xmlFilePath;
88 SetXPathDebugQuery();
89 for (int i = 1; i < argc; ++i;)
90 {
91 string arg = argv[i];
92 if (arg.StartsWith("-"))
93 {
94 if (arg == "--help" || arg == "-h")
95 {
96 PrintHelp();
97 return 0;
98 }
99 else if (arg == "--verbose" || arg == "-v")
100 {
101 verbose = true;
102 }
103 else if (arg == "--debug-parsing" || arg == "-p")
104 {
105 SetXPathDebugParsing();
106 }
107 else
108 {
109 throw Exception("unknown option '" + arg + "'");
110 }
111 }
112 else
113 {
114 if (first)
115 {
116 first = false;
117 query = arg;
118 }
119 else if (xmlFilePath.IsEmpty())
120 {
121 xmlFilePath = GetFullPath(arg);
122 }
123 else
124 {
125 PrintHelp();
126 return 1;
127 }
128 }
129 }
130 if (query.IsEmpty())
131 {
132 throw Exception("no query specified");
133 }
134 if (xmlFilePath.IsEmpty())
135 {
136 throw Exception("no xml file specified");
137 }
138 Run(1, query, xmlFilePath, verbose);
139 Run(2, query, xmlFilePath, verbose);
140 Run(3, query, xmlFilePath, verbose);
141 }
142 catch (const Exception& ex)
143 {
144 Console.Error() << ex.ToString() << endl();
145 return 1;
146 }
147 return 0;
148 }