我在 zip 檔案中讀取 XML 檔案的代碼:
“ ZipPathListSize ”是壓縮檔案的數量,@ZipPathList[i]是一個字串陣列,包含每個壓縮檔案路徑,“ modDesc / modDesc.xml ”是每個壓縮檔案中XML檔案的固定名稱。
using System.IO.Compression;
using System.Xml;
--------------------------------------------
for (int i = 0; i < ZipPathListSize; i )
{
using (ZipArchive ZipFileContent = ZipFile.OpenRead(@ZipPathList[i]))
{
XmlDocument ModDesc = new();
ZipArchiveEntry Entry = ZipFileContent.GetEntry("modDesc.xml");
if (Entry != null)
{
using (Stream stream = Entry.Open())
{
bool ExFlag = false;
try
{
ModDesc.Load(stream);
}
catch (Exception ex)
{
MessageBox.Show(Convert.ToString(@ZipPathList[i] ex));
ExFlag = true;
}
finally
{
if (ExFlag == false)
{
XmlNode MVersion = ModDesc.DocumentElement.SelectSingleNode("/modDesc");
int Version = Convert.ToInt16(MVersion.Attributes["descVersion"].InnerText);
//MessageBox.Show(@ZipPathList[i] Version); //DEBUG ONLY
}
}
}
}
else
{
MessageBox.Show("Not A Mod"); //DEBUG ONLY
}
}
}
問題是,zip 檔案中的某些 XML 檔案 (modDesc.xml) 沒有正確的宣告。如:
空的第一行
<!-- This is an empty line (Line 1), in the origin file -->
<?xml version="1.0" encoding="utf-8" standalone="no" ?> <!-- Here is Line 2 -->
<modDesc descVersion="61">
...
或錯誤的版本
<?xml version="1.1" encoding="utf-8" standalone="no" ?> <!-- 1.1? Really? -->
<modDesc descVersion="62">
但這些 XML 的所有其他部分都是正確的。
如何讀取帶有錯誤宣告的 XML?也許以某種方式忽略格式檢查并強制它讀取節點和屬性?
順便說一句,我不能手動修改任何 XML 檔案或以非編程方式修復它們。
所以,沒有 vscode,沒有記事本 :(
System.Xml.XmlException: The XML declaration must be the first node in the document, and no whitespace characters are allowed to appear before it. Line 2, position 3.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ParsePI(StringBuilder piInDtdStringBuilder)
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.Load(Stream inStream)
at FS22_ModManagerCore.ListMods.ByModFolder(String ModFolder) in
.....ListMods.cs:line 37
System.Xml.XmlException: Version number '1.1' is invalid. Line 1, position 16.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ParseXmlDeclaration(Boolean isTextDecl)
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.Load(Stream inStream)
at FS22_ModManagerCore.ListMods.ByModFolder(String ModFolder) in
......ListMods.cs:line 37
uj5u.com熱心網友回復:
至于現在,我已經自己解決了這個問題,我將在這里發布我的代碼以供一般參考。
要修復 XML 宣告問題,首先我Dispose()在.ZipArchive ZipFileContent = ZipFile.OpenRead(@ZipPathList[i])ZipArchiveMode.Update
然后將 modDesc.xml 中的所有文本加載到string[] AllTextInLine.
之后,洗掉并使用 .xml 重新創建 modDesc.xml ErrorZipContent.CreateEntry("modDesc.xml")。
最后,將正確的第一行(宣告)寫入新的 modDesc.xml 并寫入其余的AllTextInLine[].
for (int i = 0; i < ZipPathListSize; i )
{
using (ZipArchive ZipFileContent = ZipFile.OpenRead(@ZipPathList[i]))
{
XmlDocument ModDesc = new();
ZipArchiveEntry NormalEntry = ZipFileContent.GetEntry("modDesc.xml");
if (NormalEntry != null)
{
Stream NormalStream = NormalEntry.Open();
bool ExFlag = false;
try
{
ModDesc.Load(NormalStream);
}
catch (Exception ex)
{
ExFlag = true;
MessageBox.Show(Convert.ToString(@ZipPathList[i] "\n\n" ex));
Clipboard.SetText(Convert.ToString(@ZipPathList[i] "\n\n" ex));
MessageBox.Show("Try to fix" "\n\n" @ZipPathList[i]);
//ReplaceXmlDeclaration
ZipFileContent.Dispose();
using (ZipArchive ErrorZipContent = ZipFile.Open(@ZipPathList[i], ZipArchiveMode.Update))
{
ZipArchiveEntry ErrorZipEntry = ErrorZipContent.GetEntry("modDesc.xml");
string[] AllTextInLine;
using (var reader = new StreamReader(ErrorZipEntry.Open()))
{
AllTextInLine = Convert.ToString(reader.ReadToEnd()).Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
}
//MessageBox.Show(AllTextInLine[0] AllTextInLine[1] AllTextInLine[2]); //DEBUG ONLY
string Declaration = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\" ?>";
if (AllTextInLine[0] != Declaration)
{
ErrorZipEntry.Delete();
ErrorZipEntry = ErrorZipContent.CreateEntry("modDesc.xml");
using (var writer = new StreamWriter(ErrorZipEntry.Open()))
{
writer.WriteLine(Declaration); //Line 1
MessageBox.Show(@ZipPathList[i]); //DEBUG ONLY
for (int j = 1; j < AllTextInLine.Length; j ) //Start with Line 2 (Index j=1)
{
if (!AllTextInLine[j].Trim().StartsWith("<?"))
{
writer.WriteLine(AllTextInLine[j]);
}
}
}
}
ExFlag = false;
try
{
ModDesc.Load(ErrorZipEntry.Open());
}
catch (Exception exagain)
{
ExFlag = true;
MessageBox.Show(Convert.ToString(exagain));
}
}
}
finally
{
if (ExFlag == false)
{
XmlNode MVersion = ModDesc.DocumentElement.SelectSingleNode("/modDesc");
int Version = Convert.ToInt16(MVersion.Attributes["descVersion"].InnerText);
//MessageBox.Show(@ZipPathList[i] Version); //DEBUG ONLY
//if (i == ZipPathListSize - 1) //.
//{ //.
// MessageBox.Show(@ZipPathList[i] Version); //.
//} //DEBUG ONLY
}
else
{
MessageBox.Show("Fix Attempt Filed");
}
}
}
else
{
MessageBox.Show("Not A Mod"); //DEBUG ONLY
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/434197.html
上一篇:將父節點復制到根以創建多個專案
