我要求加载大型XML文件(介于0.5MB - 600MB之间),解密XML文件中的数据,并将其写入MemoryStream。
解密的数据不会停留在磁盘上非常重要。
下面是我当前的实现,它将整个XML文档加载到内存中,解密卡号并设置值,然后将修改后的XML文档复制到MemoryStream
。但是,这种实现方式并不可行,因为它将整个XML文档加载到RAM中。
public MemoryStream DecryptFile(string xmlFullPath, DateTime encryptionKey)
{
XNamespace xmlNameSpace = "http://www.xml.com/schema";
XDocument fileXDocument = XDocument.Load(xmlFullPath);
IEnumerable<XElement> cardElements =
fileXDocument
.Descendants(xmlNameSpace + "card");
// Iterate over each <card> element within the <batchRequest>.
foreach (XElement cardElement in cardElements)
{
XElement cardNumberElement = cardElement.Element(xmlNameSpace + "number");
// Read encrypted value
// Decrypt value
cardNumberElement.SetValue(decryptedCreditCard);
}
// Save the XML document, with the decrypted cards, to a memory stream.
var memoryStream = new MemoryStream();
fileXDocument.Save(memoryStream, SaveOptions.DisableFormatting);
// Rewind the stream, so that it's ready to be read from it elsewhere.
memoryStream.Position = 0;
return memoryStream;
}
我非常熟悉XmlReader
,我将其用于其他操作。
我已经考虑过能够运行XML文档,并简单地将逐个元素写入相应的MemoryStream,并最终解密数据并将其写入内存流,因为卡号出现
但是,我无法获取我正在迭代的开始/结束元素的原始XML。至少,没有解析/加载整个元素,像ReadOuterXml这样的操作允许。但我不想阅读整个元素。我只是想将原始元素逐个元素写入MemoryStream,并且只处理解密卡号码时遇到的问题。
请注意,卡号在序列化对象&#34; transaction&#34;中。即<transaction>...<number>asdfa3423jasfa</number></transaction>
那么,我如何加载(流)XML文件,修改其中的数据位,并逐步将内容写入MemoryStream?
答案 0 :(得分:1)
您必须使用XmlReader
阅读并使用XmlWriter
撰写所有内容。请记住,这是一个仅向前游标,因此您必须存储处理它时需要的任何内容。
下面是一个示例函数,用于执行类似于您需要的操作。
public static MemoryStream DecryptFile(string xmlFullPath, DateTime encryptionKey) {
var elemToLook = "number";
var inElem = false;
var number = "";
var memoryStream = new MemoryStream();
using (var writer = XmlWriter.Create(memoryStream))
using (var reader = XmlReader.Create(xmlFullPath)) {
while (reader.Read()) {
switch (reader.NodeType) {
case XmlNodeType.Element:
if (reader.Name == elemToLook)
inElem = true;
writer.WriteStartElement(reader.Name);
break;
case XmlNodeType.Text:
if (inElem) {
number = reader.Value;
// TODO: This is where your decryption code will go.
number = $"decrypted({number})";
writer.WriteString(number);
} else
writer.WriteString(reader.Value);
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
writer.WriteProcessingInstruction(reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
writer.WriteComment(reader.Value);
break;
case XmlNodeType.EndElement:
if (inElem)
inElem = false;
writer.WriteFullEndElement();
break;
case XmlNodeType.Whitespace:
writer.WriteRaw(reader.Value);
break;
}
}
}
memoryStream.Position = 0;
return memoryStream;
}
我建议您传入一个Action
委托进行处理,以便将自定义处理与标准XML处理分开
此外,如果您只想在<number>... </number>
嵌套在<transaction>...</transaction>
等其他标签内时阅读inElem
,那么在设置li
标志时需要处理在筑巢中。
答案 1 :(得分:0)
要处理XML流而不是整个文档,您可以使用XmlTextReader
来阅读流,然后使用相应的XmlTextWriter
将其放入目标MemoryStream
。
可在此处找到这些课程的文档:
XmlTextReader的 https://msdn.microsoft.com/en-us/library/system.xml.xmltextreader(v=vs.110).aspx
的XmlTextWriter https://msdn.microsoft.com/en-us/library/system.xml.xmltextwriter(v=vs.110).aspx