我正在将数据库中的blob作为字节数组加载,然后将它们放入内存流中,以便我可以将它们加载到xmldocument中进行解析。
然而,有些blob具有多个根节点,这会导致解析器爆炸。
我的解决方案是创建一个包含整个blob的新根节点。
我可以使用一个编写器添加到最后但是我无法弄清楚如何添加到开头。
我如何预先添加到流?
更新
让这个工作起来我太麻烦了。我提取的“XML”不是正确的XML,我不得不在XmlDocument加载之前添加越来越多的正则表达式来删除错误的XML。我最终使用HtmlAgilityPack来解析我的XML有效部分,并将这些部分放在他们自己的xml文档中。不是最好的解决方案,但它的工作原理。 嗟
答案 0 :(得分:4)
你不能直接。这导致两个选项:
答案 1 :(得分:4)
由于你已经有来自DB的byte[]
数组,所以在数组之前和之后将更多字节写入内存流应该很容易:
// bytes from db
byte[] multipleNodes = Encoding.UTF8.GetBytes("<first>..</first><second>..</second><third>..</third>");
using (var ms = new MemoryStream())
{
// write opening tag
byte[] newRoot = Encoding.UTF8.GetBytes("<newRoot>");
ms.Write(newRoot, 0, newRoot.Length);
ms.Write(multipleNodes, 0, multipleNodes.Length);
// write opening tag
byte[] closeNewRoot = Encoding.UTF8.GetBytes("</newRoot>");
ms.Write(closeNewRoot, 0, closeNewRoot.Length);
// reset cursor position before pass it to xmldoc
ms.Position = 0;
var xml = new XmlDocument();
xml.Load(ms);
Console.WriteLine(xml.InnerXml);
}
但是由于XmlDocument
也提供LoadXml(str)
,我觉得操纵字符串应该是更直接的解决方案:
// bytes from db
byte[] multipleNodes = Encoding.UTF8.GetBytes("<first>..</first><second>..</second><third>..</third>");
string stringFromBlob = Encoding.UTF8.GetString(multipleNodes);
string withRootNode = string.Format("<newRoot>{0}</newRoot>", stringFromBlob);
var xml = new XmlDocument();
xml.LoadXml(withRootNode);
Console.WriteLine(xml.InnerXml);
答案 2 :(得分:2)
这是我使用的那个:
public class CompositeStream : FileStream
{
Stream[] childStreams;
int currentStreamIndex = 0;
Stream currentStream;
public long totalStreamRead{get; private set;}
public CompositeStream(string pre, FileStream s_file, string post)
: base(s_file.SafeFileHandle, FileAccess.Read)
{
totalStreamRead = 0;
MemoryStream s_pre = new MemoryStream();
MemoryStream s_post = new MemoryStream();
byte[] b_pre = Encoding.UTF8.GetBytes(pre);
s_pre.Write(b_pre, 0, b_pre.Length);
s_pre.Flush();
s_pre.Seek(0, SeekOrigin.Begin);
byte[] b_post = Encoding.UTF8.GetBytes(post);
s_post.Write(b_post, 0, b_post.Length);
s_post.Flush();
s_post.Seek(0, SeekOrigin.Begin);
childStreams = new Stream[] { s_pre, s_file, s_post };
currentStream = childStreams[currentStreamIndex++];
}
public override int Read(byte[] buffer, int offset, int count)
{
int totalBytesRead = 0;
while (count > 0)
{
// Read what we can from the current stream
int numBytesRead = currentStream.Read(buffer, offset, count);
totalBytesRead += numBytesRead;
count -= numBytesRead;
offset += numBytesRead;
// If we haven't satisfied the read request,
// we have exhausted the current stream.
// Move on to the next stream and loop around to read more data.
if (count > 0)
{
// If we run out of child streams to read from...
if (currentStreamIndex >= childStreams.Length)
break; //get out
currentStream.Close();
currentStream = childStreams[currentStreamIndex++];
}
}
totalStreamRead += totalBytesRead;
return totalBytesRead;
}
}
答案 3 :(得分:1)
一种干净的方法是实现一个CompositeStreamReader
,它将接受许多流,然后按顺序读出它们。
http://blogs.msdn.com/b/paolos/archive/2010/04/15/9992360.aspx有一个实现,但你可以通过更简单的方法来解决问题。