c# 提取文檔信息的示例
事情時(shí)這樣,有用友u8的字典數(shù)據(jù)的幫助文檔一份,同事需要把里面的很多張表的字典信息給提取出來(lái),然后構(gòu)成sql語(yǔ)句,插入數(shù)據(jù)庫(kù)。字典就是一張對(duì)表里的字段的一個(gè)說(shuō)明,長(zhǎng)這樣

同事一開始是手動(dòng)復(fù)制到excel文檔在改的,他問(wèn)我有沒(méi)有什么簡(jiǎn)單的辦法,所以我就決定用代碼去實(shí)現(xiàn),把表格、表名等一些有效數(shù)據(jù)構(gòu)成對(duì)象,有了一個(gè)對(duì)象就好寫sql了。
首先,我在百度上搜索,發(fā)現(xiàn)這個(gè)chm幫助文檔能被反編譯成html,經(jīng)過(guò)一番操作,使用windows自帶的工具 hh.exe 就可以實(shí)現(xiàn)幫助文檔的反編譯。運(yùn)行cmd,直接輸入命令就行,具體命令是這樣:
hh -decompile d:\test\help help.chm
d:\test\help是反編譯后的目錄。
反編譯之后,就會(huì)得到具體的html文檔,和js、css,長(zhǎng)這樣:

test目錄是我自己建的。
后面就是查看html源碼,分析出關(guān)鍵信息的xPath路徑該怎么寫,因?yàn)檫@里我用到了.net的一款工具專門對(duì)html操作的,叫做:HtmlAgilityPack,我的翻譯是:html敏捷開發(fā)包,寫xpath比寫正則來(lái)的容易,這個(gè)包能很好的操作html的節(jié)點(diǎn),獲取html、innertext、屬性。
貼上我的關(guān)鍵方法:
public TableInfo GetTableInfo()
{
TableInfo tab = new TableInfo();
HtmlDocument doc = new HtmlDocument();
doc.Load(FullPathName, Encoding.GetEncoding("gb2312"), true);
if (doc == null)
{
throw new NullReferenceException(FullPathName + "\r\n沒(méi)有加載出文檔");
}
string pathGetTableName = "/html/head/title";
string pathGetTableDesc = "/div/p";
String pathGetTd = "/div/table/tr";
var nodeTitle=doc.DocumentNode.SelectSingleNode(pathGetTableName);
if (null != nodeTitle)
{
tab.TableName = nodeTitle.InnerText.Split(new char[1] { ' '})[0].Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("&", "").Replace("nbsp;", "");
}
var nodeBody = doc.GetElementbyId("pagebody");
var str = nodeBody.OuterHtml;
var doc1 = new HtmlDocument();
doc1.LoadHtml(str);
var nodeDesc = doc1.DocumentNode.SelectSingleNode(pathGetTableDesc);
if (null != nodeDesc)
{
tab.tableDescription = nodeDesc.InnerText.Split(new char[1] { ' ' })[0].Replace("\r","").Replace("\n", "").Replace("\t", "").Replace("&", "").Replace("nbsp;", "");
}
var nodesTr = doc1.DocumentNode.SelectNodes(pathGetTd);
if (nodesTr == null)
{
return tab;
}
List<TabFieldInfo> lists = new List<TabFieldInfo>();
for (var i = 1; i < nodesTr.Count(); i++)
{
var childs = nodesTr[i].ChildNodes;
if (childs == null)
{
continue;
}
TabFieldInfo fi = new TabFieldInfo();
if (childs.Count <= 5)
{
continue;
}
fi.ColumnName = childs[1].ChildNodes[1].InnerText.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("&", "").Replace("nbsp;", "");
fi.Description = childs[2].InnerText.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("&", "").Replace("nbsp;", "");
fi.Datatype = childs[3].InnerText.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("&", "").Replace("nbsp;", "");
fi.Length = childs[4].InnerText.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("&", "").Replace("nbsp;", "");
fi.AllowNulls = childs[5].InnerText.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("&", "").Replace("nbsp;", "");
lists.Add(fi);
}
tab.fields = lists;
return tab;
}
這里還出現(xiàn)一個(gè)問(wèn)題,“指定的路徑不合法”,原因是,我直接點(diǎn)擊文件右鍵-》屬性-》安全 把那里的文件路經(jīng)復(fù)制到代碼上去了,其實(shí)這樣復(fù)制,會(huì)造成路徑字符串最開始的地方有個(gè)特殊字符,在vs里是隱藏的,后來(lái)我就復(fù)制地址欄上的路徑,就沒(méi)問(wèn)題了。
最后,需要完善的是,通過(guò)讀取目錄,把目錄中的所有html結(jié)尾的文件遍歷,并過(guò)濾出需要的表,在構(gòu)建對(duì)象。
以上就是c# 提取文檔信息的示例的詳細(xì)內(nèi)容,更多關(guān)于c# 提取文檔信息的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#數(shù)據(jù)結(jié)構(gòu)之雙向鏈表(DbLinkList)實(shí)例詳解
這篇文章主要介紹了C#數(shù)據(jù)結(jié)構(gòu)之雙向鏈表(DbLinkList),結(jié)合實(shí)例形式較為詳細(xì)的講解了雙向鏈表的概念及C#實(shí)現(xiàn)雙向鏈表的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
解決C#獲取鼠標(biāo)相對(duì)當(dāng)前窗口坐標(biāo)的實(shí)現(xiàn)方法
本篇文章是對(duì)在C#中獲取鼠標(biāo)相對(duì)當(dāng)前窗口坐標(biāo)的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C# 運(yùn)用params修飾符來(lái)實(shí)現(xiàn)變長(zhǎng)參數(shù)傳遞的方法
一般來(lái)說(shuō),參數(shù)個(gè)數(shù)都是固定的,定義為集群類型的參數(shù)可以實(shí)現(xiàn)可變數(shù)目參數(shù)的目的,但是.NET提供了更靈活的機(jī)制來(lái)實(shí)現(xiàn)可變數(shù)目參數(shù),這就是使用params修飾符2013-09-09
C#中Socket通信編程的異步實(shí)現(xiàn)流程分析
Socket編程的異步實(shí)現(xiàn)是指按照異步過(guò)程來(lái)實(shí)現(xiàn)Socket編程,即在完成了一次調(diào)用后通過(guò)狀態(tài)、通知和回調(diào)來(lái)告知調(diào)用者,本文給大家介紹C#中Socket通信編程的異步實(shí)現(xiàn)流程分析,感興趣的朋友一起看看吧2024-12-12
.NET平臺(tái)的一種方便快捷的服務(wù)注冊(cè)方案
這篇文章主要介紹了.NET平臺(tái)的一種方便快捷的服務(wù)注冊(cè)方案的相關(guān)資料,需要的朋友可以參考下2023-08-08
C#線程委托BeginInvoke與EndInvoke的用法
這篇文章介紹了C#線程委托BeginInvoke與EndInvoke的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07

