C#手工解析XML

唉,已经好久没逛园子了,今天没事来写一点

前段时间遇到个情况,由于引用的程序集(为XNA wp的)所依赖的System.XML的版本不一样,导致无法使用系统的XML解析。本来想从网上找个自己实现XML算法的程序,还真不好找,不过也是,谁没事去写这个东西。

没办法,就自己写了,当然,这个比较简单,因为我所使用的就这个简单功能,有需要的朋友可以看看,也就免得以后不好找了,根据需要可以自由扩充。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Collections;

namespace GameEngine.XNA

{

/// <summary>

/// XML解析器

/// </summary>

public class XmlParser

{

/// <summary>

/// 加载XML

/// </summary>

/// <param name="xml"></param>

public void Load(string xml)

{

InnerXML = xml;

Root = new XmlNode();

Root._internalXML = InnerXML;

Root.Parser();

}

public string InnerXML { get; set; }

/// <summary>

/// 根节点

/// </summary>

public XmlNode Root { get; set; }

}

/// <summary>

/// XML属性

/// </summary>

public class XmlAttribute

{

public string Name { get; set; }

public string Value { get; set; }

internal string _internalXML;

internal void Parser()

{

string[] exp = _internalXML.Split('=');

Name = exp[0];

Value = exp[1].Substring(1, exp[1].Length - 2);

}

}

/// <summary>

/// XML节点

/// </summary>

public class XmlNode

{

public string Name { get; set; }

public string Value { get; set; }

/// <summary>

/// 子节点

/// </summary>

public List<XmlNode> Nodes { get; set; }

public List<XmlAttribute> Attributes { get; set; }

public string InnerXML { get; set; }

internal string _internalXML;

private int start;

private int end;

internal int current;

public XmlNode()

{

Nodes = new List<XmlNode>();

Attributes = new List<XmlAttribute>();

}

private void ParserXML()

{

InnerXML = InternalParserXML();

}

private string InternalParserXML()

{

StringBuilder builder = new StringBuilder();

builder.Append("<");

builder.Append(Name);

for (int i = 0; i < Attributes.Count; i++)

{

builder.Append(" ");

builder.Append(Attributes[i].Name);

builder.Append("=");

builder.Append("\"");

builder.Append(Attributes[i].Value);

builder.Append("\"");

}

builder.Append(">");

for (int i = 0; i < Nodes.Count; i++)

{

builder.Append(Nodes[i].InternalParserXML());

}

builder.Append("</");

builder.Append(Name);

builder.Append(">");

return builder.ToString();

}

internal void Parser()

{

NodeType type = GetCurrentNodeType();

ReadBeginBlock();

while (true)

{

type = GetCurrentNodeType();

if (type == NodeType.BeginNode)

{

XmlNode node = new XmlNode();

node._internalXML = _internalXML;//.Substring(current, _internalXML.Length - current);

node.start = current;

node.current = current;

node.Parser();

Nodes.Add(node);

current = node.end;

}

else if (type == NodeType.Text)

{

ReadValue();

}

else if (type == NodeType.EndNode)

{

ReadEndBlock();

break;

}

}

}

public enum NodeType

{

BeginNode,

EndNode,

Text

}

private NodeType GetCurrentNodeType()

{

if (_internalXML[current] == '<' && _internalXML[current + 1] != '/')

{

return NodeType.BeginNode;

}

else if (_internalXML[current] == '<' && _internalXML[current + 1] == '/')

{

return NodeType.EndNode;

}

else if (_internalXML[current] != '<')

{

return NodeType.Text;

}

throw new Exception();

}

private void ReadBeginBlock()

{

current++;

int posend = _internalXML.IndexOf('>',start);

string nodeinner = _internalXML.Substring(current, posend - current);

string [] atts = nodeinner.Split(' ');

Name = atts[0];

if (atts.Length > 1)

{

for (int i = 1; i < atts.Length; i++)

{

XmlAttribute att = new XmlAttribute();

att._internalXML = atts[i];

att.Parser();

Attributes.Add(att);

}

}

posend++;

current = posend;

}

private void ReadValue()

{

int posend = _internalXML.IndexOf('<', current);

Value = _internalXML.Substring(current, posend - current);

current = posend;

}

private void ReadEndBlock()

{

int posend = _internalXML.IndexOf('>', current);

posend++;

current = posend;

InnerXML = _internalXML.Substring(start, current-start);

end = current;

}

}

}