You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
14 KiB
C#

10 months ago
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
/// <summary>
/// XMLParser 简易XML解析方法
///string str = File.ReadAllText(@"config.xml", Encoding.UTF8); //读取XML文件
/////MessageBox.Show(str);
///XMLParser xmlParser = new XMLParser();
///XMLNode xn = xmlParser.Parse(str);
///server = xn.GetValue("items>0>server>0>_text");
/// database = xn.GetValue("items>0>database>0>_text");
/// XMLNode temp = xn.GetNode("items>0>res>0");
///string basePath = temp.GetValue("@basePath");//或直接 basePath=xn.GetValue("items>0>res>0>@basePath");
///当然xml文件内容为
///<? xml version="1.0" encoding="utf-8" ?>
///<items>
/// <server>192.168.52.148</server>
/// <database>world</database>
/// <port>3306</port>
/// <uid>wtx</uid>
/// <password>123456</password>
/// <res basePath = "d:\Resources" language="zh_CN" />
/// /// 得到的解析结果是
//server=192.168.52.148 ; database=world; basePath=d:\Resources
/// </items>
/// </summary>
namespace DSWeb.Areas.CommMng.DAL
{
public class XMLParser
{
private char LT = '<';
private char GT = '>';
private char SPACE = ' ';
private char QUOTE = '"';
private char QUOTE2 = '\'';
private char SLASH = '/';
private char QMARK = '?';
private char EQUALS = '=';
private char EXCLAMATION = '!';
private char DASH = '-';
//private char SQL = '[';
private char SQR = ']';
public XMLNode Parse(string content)
{
XMLNode rootNode = new XMLNode();
rootNode["_text"] = "";
string nodeContents = "";
bool inElement = false;
bool collectNodeName = false;
bool collectAttributeName = false;
bool collectAttributeValue = false;
bool quoted = false;
string attName = "";
string attValue = "";
string nodeName = "";
string textValue = "";
bool inMetaTag = false;
bool inComment = false;
bool inCDATA = false;
XMLNodeList parents = new XMLNodeList();
XMLNode currentNode = rootNode;
for (int i = 0; i < content.Length; i++)
{
char c = content[i];
char cn = '~'; // unused char
char cnn = '~'; // unused char
char cp = '~'; // unused char
if ((i + 1) < content.Length) cn = content[i + 1];
if ((i + 2) < content.Length) cnn = content[i + 2];
if (i > 0) cp = content[i - 1];
if (inMetaTag)
{
if (c == QMARK && cn == GT)
{
inMetaTag = false;
i++;
}
continue;
}
else
{
if (!quoted && c == LT && cn == QMARK)
{
inMetaTag = true;
continue;
}
}
if (inComment)
{
if (cp == DASH && c == DASH && cn == GT)
{
inComment = false;
i++;
}
continue;
}
else
{
if (!quoted && c == LT && cn == EXCLAMATION)
{
if (content.Length > i + 9 && content.Substring(i, 9) == "<![CDATA[")
{
inCDATA = true;
i += 8;
}
else
{
inComment = true;
}
continue;
}
}
if (inCDATA)
{
if (c == SQR && cn == SQR && cnn == GT)
{
inCDATA = false;
i += 2;
continue;
}
textValue += c;
continue;
}
if (inElement)
{
if (collectNodeName)
{
if (c == SPACE)
{
collectNodeName = false;
}
else if (c == GT)
{
collectNodeName = false;
inElement = false;
}
if (!collectNodeName && nodeName.Length > 0)
{
if (nodeName[0] == SLASH)
{
// close tag
if (textValue.Length > 0)
{
currentNode["_text"] += textValue;
}
textValue = "";
nodeName = "";
currentNode = parents.Pop();
}
else
{
if (textValue.Length > 0)
{
currentNode["_text"] += textValue;
}
textValue = "";
XMLNode newNode = new XMLNode();
newNode["_text"] = "";
newNode["_name"] = nodeName;
if (currentNode[nodeName] == null)
{
currentNode[nodeName] = new XMLNodeList();
}
XMLNodeList a = (XMLNodeList)currentNode[nodeName];
a.Push(newNode);
parents.Push(currentNode);
currentNode = newNode;
nodeName = "";
}
}
else
{
nodeName += c;
}
}
else
{
if (!quoted && c == SLASH && cn == GT)
{
inElement = false;
collectAttributeName = false;
collectAttributeValue = false;
if (attName.Length > 0)
{
if (attValue.Length > 0)
{
currentNode["@" + attName] = attValue;
}
else
{
currentNode["@" + attName] = true;
}
}
i++;
currentNode = parents.Pop();
attName = "";
attValue = "";
}
else if (!quoted && c == GT)
{
inElement = false;
collectAttributeName = false;
collectAttributeValue = false;
if (attName.Length > 0)
{
currentNode["@" + attName] = attValue;
}
attName = "";
attValue = "";
}
else
{
if (collectAttributeName)
{
if (c == SPACE || c == EQUALS)
{
collectAttributeName = false;
collectAttributeValue = true;
}
else
{
attName += c;
}
}
else if (collectAttributeValue)
{
if (c == QUOTE || c == QUOTE2)
{
if (quoted)
{
collectAttributeValue = false;
currentNode["@" + attName] = attValue;
attValue = "";
attName = "";
quoted = false;
}
else
{
quoted = true;
}
}
else
{
if (quoted)
{
attValue += c;
}
else
{
if (c == SPACE)
{
collectAttributeValue = false;
currentNode["@" + attName] = attValue;
attValue = "";
attName = "";
}
}
}
}
else if (c == SPACE)
{
}
else
{
collectAttributeName = true;
attName = "" + c;
attValue = "";
quoted = false;
}
}
}
}
else
{
if (c == LT)
{
inElement = true;
collectNodeName = true;
}
else
{
textValue += c;
}
}
}
return rootNode;
}
}
public class XMLNode : Hashtable
{
public XMLNodeList GetNodeList(string path)
{
return GetObject(path) as XMLNodeList;
}
public XMLNode GetNode(string path)
{
return GetObject(path) as XMLNode;
}
public string GetValue(string path)
{
return GetObject(path) as string;
}
private object GetObject(string path)
{
string[] bits = path.Split('>');
XMLNode currentNode = this;
XMLNodeList currentNodeList = null;
bool listMode = false;
object ob;
for (int i = 0; i < bits.Length; i++)
{
if (listMode)
{
currentNode = (XMLNode)currentNodeList[int.Parse(bits[i])];
ob = currentNode;
listMode = false;
}
else
{
ob = currentNode[bits[i]];
if (ob is ArrayList)
{
currentNodeList = (XMLNodeList)(ob as ArrayList);
listMode = true;
}
else
{
// reached a leaf node/attribute
if (i != (bits.Length - 1))
{
// unexpected leaf node
string actualPath = "";
for (int j = 0; j <= i; j++)
{
actualPath = actualPath + ">" + bits[j];
}
//Debug.Log("xml path search truncated. Wanted: " + path + " got: " + actualPath);
}
return ob;
}
}
}
if (listMode)
return currentNodeList;
else
return currentNode;
}
}
public class XMLNodeList : ArrayList
{
public XMLNode Pop()
{
XMLNode item = null;
item = (XMLNode)this[this.Count - 1];
this.Remove(item);
return item;
}
public int Push(XMLNode item)
{
Add(item);
return this.Count;
}
}
}