#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

197 lines
5.8 KiB

// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christoph Wille" email="christophw@alphasierrapapa.com"/>
// <version value="$version"/>
// </file>
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Windows.Forms;
using System.Xml;
namespace ICSharpCode.HelpConverter
{
public class HhcFileParser
{
string hhcFileContents;
string chmName;
string basePath;
ArrayList rootTreeNodes = new ArrayList();
XmlNode currentNode = null;
public HhcFileParser(string basePath)
{
this.basePath = basePath;
}
void LoadHhcFile(string fileName)
{
FileInfo fi = new FileInfo(basePath + Path.DirectorySeparatorChar + fileName);
StreamReader sr = fi.OpenText();
hhcFileContents = sr.ReadToEnd();
sr.Close();
}
void MakeXmlCompliant()
{
StringBuilder strFixup =
new StringBuilder(Regex.Replace(hhcFileContents,
"(?'start'<param\\s[^>]*)(?'end'\"/?>)",
"${start}\"/>"));
strFixup.Replace("</OBJECT></UL>", "</OBJECT></LI></UL>");
strFixup.Replace("</OBJECT><LI>", "</OBJECT></LI><LI>");
strFixup.Replace("</OBJECT><UL><LI>", "</OBJECT></LI><UL><LI>");
hhcFileContents = strFixup.ToString();
}
void Load(string fileName)
{
LoadHhcFile(fileName);
MakeXmlCompliant();
}
public void Parse(XmlDocument helpFileDocument, XmlNode currentNode, string hhcFileName, string chmName)
{
this.chmName = chmName;
Load(hhcFileName);
XmlDocument doc = new XmlDocument();
doc.LoadXml(hhcFileContents);
XmlNode root = doc.ChildNodes[0];
XmlNode outermostList = null;
switch (root.Name.ToLower()) {
case "ul":
outermostList = root;
break;
case "html": // this would be well-formed HTML
outermostList = root["BODY"]["UL"];
break;
case "#comment": // this is NDoc malformed HTML
outermostList = doc.ChildNodes[1];
break;
default:
// this is nothing we can read; please send us the .hhc file
break;
}
if (null == outermostList) {
Console.WriteLine("Format of file not valid, cannot find root <UL> node");
return;
}
this.currentNode = currentNode;
EvaluateLevel(helpFileDocument, outermostList);
// quick & dirty overview of the structure
// Console.WriteLine("---------------------------");
// DumpElement(root, 0);
}
void EvaluateLevel(XmlDocument helpFileDocument, XmlNode currentLevel)
{
for (int i = 0; i < currentLevel.ChildNodes.Count; i++) {
XmlNode currentElement = currentLevel.ChildNodes[i];
// we need a lookup on the next node - is it a UL, then the current node
// node needs to be displayed as a folder, otherwise it is a non-expandable
// leaf node in our tree
bool bIsFolderNode = false;
if (i < (currentLevel.ChildNodes.Count - 1)) {
XmlNode nextElement = currentLevel.ChildNodes[i + 1];
if ("UL" == nextElement.Name) bIsFolderNode = true;
}
string strNodeName, strNodeUrl;
if (bIsFolderNode) {
GetNodeInformation(currentElement["OBJECT"], out strNodeName, out strNodeUrl);
// we need to create a folder and continue traversing
XmlElement folderElement = helpFileDocument.CreateElement("HelpFolder");
XmlAttribute attrib = helpFileDocument.CreateAttribute("name");
attrib.InnerText = strNodeName;
folderElement.Attributes.Append(attrib);
currentNode.AppendChild(folderElement);
XmlNode savedNode = currentNode;
currentNode = folderElement;
EvaluateLevel(helpFileDocument, currentLevel.ChildNodes[i + 1]);
currentNode = savedNode;
} else {
// we have a leaf node here, but we need to ignore UL's, those are handled by
// their parents above
if ("UL" == currentElement.Name) {
// we do nothing with this element
} else {
GetNodeInformation(currentElement["OBJECT"], out strNodeName, out strNodeUrl);
XmlElement helpTopic = helpFileDocument.CreateElement("HelpTopic");
XmlAttribute attrib = helpFileDocument.CreateAttribute("name");
attrib.InnerText = strNodeName;
helpTopic.Attributes.Append(attrib);
attrib = helpFileDocument.CreateAttribute("link");
attrib.InnerText = chmName + "::/" + strNodeUrl;
helpTopic.Attributes.Append(attrib);
currentNode.AppendChild(helpTopic);
}
}
}
}
void GetNodeInformation(XmlNode theNode, out string NodeName, out string NodeUrl)
{
// <param name="Name" value="name of node"/> and url are read from OBJECT node
string strParamType, strParamValue;
strParamType = strParamValue = NodeName = NodeUrl = "";
for (int i = 0; i < theNode.ChildNodes.Count; i++) {
XmlNode currentParam = theNode.ChildNodes[i];
// we work with param nodes only, anything else cannot be handled here
if ("param" != currentParam.Name) {
return;
}
// if any of the below two XmlAttribute objects is not available,
// we will get a null ref exception
try {
strParamType = currentParam.Attributes["name"].Value;
strParamValue = currentParam.Attributes["value"].Value;
} catch {
strParamType = ""; // because of the switch statement, we need a default value when it fails
}
switch (strParamType) {
case "Name":
NodeName = strParamValue;
break;
case "Local":
NodeUrl = strParamValue;
break;
}
}
}
// for internal use only - dump entire structure to the console.
void DumpElement(XmlNode el, int nDepth)
{
string strTree = new String(' ', nDepth);
foreach(XmlNode subEl in el.ChildNodes) {
Console.WriteLine(strTree + subEl.Name);
DumpElement(subEl, nDepth+1);
}
}
}
}