我有以下输入字符串,来自10MB文本文件
string data = "0x52341\n0x52341<?xml version=\"1.0\" encoding=\"UTF-8\"?><element1 value=\"3\"><sub>1</sub></element1>0x52341\n0x52341 <element1><sub><element>2</element></sub></element1>0x52341<element2><sub>3</sub></element2> <element2><sub>4</sub></element2>0x4312";
现在我想通过element1
和element2
XML节点
这种情况下的结果应该是
output[0] = "<element1 value="3"><sub>1</sub></element1>";
output[1] = "<element1><sub><element>2</element></sub></element1>";
output[2] = "<element2><sub>3</sub></element2>";
output[3] = "<element2><sub>4</sub></element2>";
我的efford:
我已经尝试过正则表达式,但是在那个大文件的情况下这很慢,我也试过了
string[] output= input.Split(new string[] { "<element1>", "<element2>" }, StringSplitOptions.None);
string.Split()
迂回曲折,因为它抛出了内存异常,并且在分裂时删除了删除者。
问题: 有没有一种简单的方法可以解析我的文本文件中的那些xml元素?
更新 我简化了我的文件,因为我无法在SO中发布整个10MB文件 - 有时xml元素之间有0x1234值,有时候不是
答案 0 :(得分:3)
如果你能保证每个<elementX></elementX>
片段都是格式良好的XML节点(可以这么说),请将整个字符串包装在<elements> ... </elements>
中并使用它来处理它标准的.NET方法,无论是XmlDocument
,Linq to XML还是其他适合你的方法。
答案 1 :(得分:1)
编辑: 一个更快的替代方案(因为它没有使用正则表达式)不会替换元素内容中的0x ...片段将是以下一个:
string data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>0x52341<element1 value=\"3\"><sub>1</sub></element1>0x234512 <element1><sub><element>2</element></sub></element1>0x52341<element2><sub>3</sub></element2> <element2><sub>4</sub></element2>0x4312";
XmlReaderSettings xrs = new XmlReaderSettings();
xrs.ConformanceLevel = ConformanceLevel.Fragment;
XDocument doc = new XDocument(new XElement("root"));
XElement root = doc.Descendants().First();
using(var ms = new StreamWriter(new MemoryStream()))
{
ms.Write(data);
ms.Flush();
ms.BaseStream.Position = 0;
using (StreamReader fs = new StreamReader(ms.BaseStream))
//using (StreamReader fs = new StreamReader("file.xml"))
{
using (XmlReader rdr = XmlReader.Create(fs, xrs))
{
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element)
{
root.Add(XElement.Load(rdr.ReadSubtree()));
}
}
}
}
}
您还可以使用另一个StreamReader构造函数直接从该文件中读取(删除StreamWriter部分)
答案 2 :(得分:0)
这是一个可以执行此操作的控制台应用程序:
class Program
{
static void Main(string[] args)
{
string source = "0x52341<element1 value=\"3\"><sub>1</sub></element1>0x234512 <element1><sub><element>2</element></sub></element1>0x52341<element2><sub>3</sub></element2> <element2><sub>4</sub></element2>0x4312";
List<string> components = new List<string>();
while (source.Length > 0)
{
int start = source.IndexOf('<');
if (-1 == start)
break;
int next = source.IndexOf("0x", start, StringComparison.OrdinalIgnoreCase);
if (-1 == next)
break;
components.Add(source.Substring(start, next - start));
source = source.Substring(next);
}
foreach (string s in components)
Console.WriteLine(s);
Console.ReadLine();
}
}
尝试一下。
答案 3 :(得分:0)
将文件作为流处理 - 查找开始和结束元素,仅解析进程中的那些元素:
using (var stream = File.OpenRead("..."))
{
StringBuilder builder = null;
StringBuilder xml = null;
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
while (!reader.EndOfStream)
{
char c = (char)reader.Read();
if (c == '<' && builder == null)
{
builder = new StringBuilder();
}
if (builder != null)
{
builder.Append(c);
}
if (xml != null)
{
xml.Append(c);
}
if (c == '>')
{
var token = builder.ToString();
if (xml == null)
{
if (token.StartsWith("<element1", StringComparison.Ordinal) || token.StartsWith("<element2", StringComparison.Ordinal))
{
xml = new StringBuilder("<?xml version='1.0' encoding='utf-8' ?>");
xml.Append(token);
}
}
else
{
if (token.StartsWith("</element1", StringComparison.Ordinal) || token.StartsWith("</element2", StringComparison.Ordinal))
{
XElement element = XElement.Parse(xml.ToString());
// do something with the element
xml = null;
}
}
builder = null;
}
}
}
}