|
using System;
using System.Data;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.XPath;
using System.Collections;
namespace AdvancedXPathAnalyzer
{
public class AXAEngine {
private int indentLevel;
private XPathDocument document;
private XPathNavigator navigator;
private XPathExpression expression;
private XmlNamespaceManager namespaceManager;
private string xmlSourceFile;
private ArrayList DetectedNamespaces;
#region Contructors
public AXAEngine(string xmlSourceFile) {
indentLevel = 0;
this.xmlSourceFile = xmlSourceFile;
//Instantiate XPathDocument and load XML document
document = new XPathDocument(xmlSourceFile);
//Instantiate XPathNavigator
navigator = document.CreateNavigator();
}
#endregion
#region Public Methods
public DataView Analyze(string xpathQuery, Array namespaces) {
XPathNodeIterator nodeIterator;
DataTable resultTable;
DataRow resultRow;
string attribute;
int totalNode = 0;
string nodeType;
//Create temporary table to keep query result
resultTable = new DataTable("QueryResult");
resultTable.Columns.Add("node", Type.GetType("System.String"));
resultTable.Columns.Add("value", Type.GetType("System.String"));
resultTable.Columns.Add("attribute", Type.GetType("System.String"));
//Create a namespace manager
namespaceManager = new XmlNamespaceManager(new NameTable());
foreach(string ns in namespaces) {
int tokenPos = ns.IndexOf(':');
string prefix = ns.Substring(0, tokenPos);
string uri = ns.Substring(tokenPos+1);
namespaceManager.AddNamespace(prefix.Trim(), uri.Trim());
}
//Instantiate XPathExpression
expression = navigator.Compile(xpathQuery);
if (namespaceManager != null)
expression.SetContext(namespaceManager);
//Execute XPath query
nodeIterator = navigator.Select(expression);
//Iterate through the resultant node set
while (nodeIterator.MoveNext()) {
//Count the number of nodes in the node set
totalNode += 1;
//Get the current node as XPathNavigator object
navigator = nodeIterator.Current;
//Create a new row in the temporary table
resultRow = resultTable.NewRow();
//Fill the first column of new row
switch (navigator.NodeType) {
case XPathNodeType.Element :
nodeType = "<>";
break;
case XPathNodeType.Attribute :
nodeType = "=";
break;
case XPathNodeType.Text :
nodeType = "Abc";
break;
case XPathNodeType.Comment :
nodeType = "<!>";
break;
default :
nodeType = "";
break;
}
resultRow["node"] = string.Format("<font color=\"red\"><b>{0}</b></font>{1}", nodeType, navigator.Name);
//Fill the second column of new row
if (navigator.MoveToFirstChild()) {
resultRow["value"] = RenderTree();
navigator.MoveToParent();
} else {
resultRow["value"] = navigator.Value;
}
//Fill the third column of new row
attribute = string.Empty;
if (navigator.NodeType == XPathNodeType.Attribute) {
resultRow["attribute"] = "n/a";
} else {
//Iterate through attributes if any
if (navigator.MoveToFirstAttribute()) {
do {
attribute += string.Format("{0}: {1}<br>", navigator.Name, navigator.Value);
} while (navigator.MoveToNextAttribute());
navigator.MoveToParent();
resultRow["attribute"] = attribute;
}
}
//Effectively add the new row to the temporary table
resultTable.Rows.Add(resultRow);
}
return resultTable.DefaultView;
}
public Array DetectNamespaces() {
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlSourceFile);
DetectedNamespaces = new ArrayList();
XmlNode xmlNode = xmlDoc.DocumentElement;
NamespaceDiscover(xmlNode);
return DetectedNamespaces.ToArray();
}
#endregion
#region Private Methods
private string RenderTree() {
StringBuilder sb = new StringBuilder();
//Iterate through all siblings
do {
switch (navigator.NodeType) {
case XPathNodeType.Text :
sb.Append(navigator.Value);
break;
case XPathNodeType.Comment :
sb.AppendFormat("<!-- {0} --><br>", navigator.Value);
break;
default :
//Render indent
sb.Append(RenderHTMLSpace(indentLevel));
//Render opening tag
sb.Append("<");
sb.Append(navigator.Name);
//Render attributes if any
if (navigator.MoveToFirstAttribute()) {
do {
sb.AppendFormat(" {0}=\"{1}\"", navigator.Name, navigator.Value);
} while(navigator.MoveToNextAttribute());
navigator.MoveToParent();
}
sb.Append(">");
//Render child nodes if any
if (navigator.MoveToFirstChild()) {
if (navigator.NodeType != XPathNodeType.Text) {
sb.Append("<br>");
}
indentLevel += 2;
//Invoke this function recursively
sb.Append(RenderTree());
indentLevel -= 2;
//Move back to the parent node
navigator.MoveToParent();
}
//Render closing tag
sb.AppendFormat("</{0}><br>", navigator.Name);
break;
}
} while (navigator.MoveToNext());
return sb.ToString();
}
private string RenderHTMLSpace(int totalSpace) {
StringBuilder spaces = new StringBuilder();
if (totalSpace > 0)
spaces.Insert(0, " ", totalSpace);
return spaces.ToString();
}
private void NamespaceDiscover(XmlNode xNode) {
string nsPrefix;
string nsUri;
namespaceManager = new XmlNamespaceManager(new NameTable());
if (xNode.NodeType == XmlNodeType.Element) {
if (xNode.Attributes.Count > 0) {
int attrNum = 0;
while (attrNum < xNode.Attributes.Count) {
if (xNode.Attributes[attrNum].Name.StartsWith("xmlns")) {
string nsDef = xNode.Attributes[attrNum].Name.Split('=')[0];
if (nsDef != "xmlns") {
nsPrefix = nsDef.Split(':')[1];
}
else {
nsPrefix = "def";
}
nsUri = xNode.Attributes[attrNum].Value;
DetectedNamespaces.Add(string.Format("{0}: {1}", nsPrefix, nsUri));
}
attrNum++;
}
}
if (xNode.HasChildNodes) {
int elemNum = 0;
while (elemNum < xNode.ChildNodes.Count) {
NamespaceDiscover(xNode.ChildNodes[elemNum]);
elemNum++;
}
}
}
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Born in 1977, works as a freelancer, focusing on Database / Software Architecture.
In the free time writes articles for two of the major Italian programming magazines (Computer Programming and VBJ) and also develops nice and useful programs.
His major interests and skills are the .NET framework (C# in particular) and SQL Server.