[英]Best way to read, modify, and write XML
我的計划是使用C#程序讀取XML文檔,搜索要更改的特定條目,然后寫出修改后的文檔。 但是,我變得困惑不解,因為很難區分元素,無論它們是使用我用來讀取文件的XmlTextReader開頭還是結尾。 我可以提供一些建議,使我走上正確的道路。
該文檔是HTML文檔,因此可以想象,它非常復雜。
我想在HTML文檔中搜索元素ID,因此例如查找並更改src。
<img border="0" src="bigpicture.png" width="248" height="36" alt="" id="lookforthis" />
如果它實際上是有效的XML,並且很容易裝入內存,那么我每次都會選擇LINQ to XML ( XDocument
, XElement
等)。 到目前為止,這是我使用過的最好的XML API。 形成查詢很容易,構造新元素也很容易。
您可以在適當的地方使用XPath,也可以使用內置的軸方法( Elements()
, Descendants()
, Attributes()
等)。 如果您可以讓我們知道您遇到什么困難,我很樂於幫助您確定如何用LINQ to XML來表達它們。
另一方面,如果這是不是有效XML的HTML,那么您將面臨更多困難-因為XML通用語法希望可以與有效XML文檔一起使用。 您當然可以先使用HTMLTidy ,但這可能會產生不良影響。
對於您的特定示例:
XDocument doc = XDocument.Load("file.xml");
foreach (var img in doc.Descendants("img"))
{
// src will be null if the attribute is missing
string src = (string) img.Attribute("src");
img.SetAttributeValue("src", src + "with-changes");
}
您正在處理的文件是否相對較小? 如果是這樣,則可以使用XmlDocument對象將它們加載到內存中,對其進行修改,然后將所做的更改寫回。
XmlDocument doc = new XmlDocument();
doc.Load("path_to_input_file");
// Make changes to the document.
using(XmlTextWriter xtw = new XmlTextWriter("path_to_output_file", Encoding.UTF8)) {
xtw.Formatting = Formatting.Indented; // optional, if you want it to look nice
doc.WriteContentTo(xtw);
}
根據輸入XML的結構,這可以使您的解析代碼更簡單。
這是我編寫的用於修改IAR EWARM項目(ewp)文件的工具,為該項目添加了鏈接器定義。 在命令行中,使用2個參數(輸入和輸出文件名(* .ewp))運行它。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace ewp_tool
{
class Program
{
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
doc.Load(args[0]);
XmlNodeList list = doc.SelectNodes("/project/configuration[name='Debug']/settings[name='ILINK']/data/option[name='IlinkConfigDefines']/state");
foreach(XmlElement x in list) {
x.InnerText = "MAIN_APP=1";
}
using (XmlTextWriter xtw = new XmlTextWriter(args[1], Encoding.UTF8))
{
//xtw.Formatting = Formatting.Indented; // leave this out, it breaks EWP!
doc.WriteContentTo(xtw);
}
}
}
}
XML的結構如下所示
<U+FEFF><?xml version="1.0" encoding="iso-8859-1"?>
<project>
<fileVersion>2</fileVersion>
<configuration>
<name>Debug</name>
<toolchain>
<name>ARM</name>
</toolchain>
<debug>1</debug>
...
<settings>
<name>ILINK</name>
<archiveVersion>0</archiveVersion>
<data>
...
<option>
<name>IlinkConfigDefines</name>
<state>MAIN_APP=0</state>
</option>
如果您有較小的文檔適合計算機內存,則可以使用XmlDocument
。 否則,您可以使用XmlReader
遍歷文檔。
使用XmlReader
您可以使用以下XmlReader
找出元素類型:
while (xml.Read()) {
switch xml.NodeType {
case XmlNodeType.Element:
//Do something
case XmlNodeType.Text:
//Do something
case XmlNodeType.EndElement:
//Do something
}
}
對於手頭的任務-(以正式的方式閱讀現有文檔,編寫和修改),我將通過XslCompiledTransform運行XPathDocument 。
在無法形式化,沒有預先存在的文檔或通常需要更多自適應邏輯的地方,我會像Skeet所說的那樣使用LINQ和XDocument。
基本上,如果任務是轉換,則為XSLT;如果任務是操縱,則為LINQ。
對於此類事情,我最喜歡的工具是HtmlAgilityPack 。 我用它將復雜的HTML文檔解析為LINQ可查詢的集合。 它是用於查詢和解析HTML(通常不是有效的XML)的極其有用的工具。
對於您的問題,代碼如下所示:
var htmlDoc = HtmlAgilityPack.LoadDocument(stringOfHtml);
var images = htmlDoc.DocumentNode.SelectNodes("//img[id=lookforthis]");
if(images != null)
{
foreach (HtmlNode node in images)
{
node.Attributes.Append("alt", "added an alt to lookforthis images.");
}
}
htmlDoc.Save('output.html');
一種相當簡單的方法是創建一個新的XmlDocument
,然后使用Load()
方法填充它。 獲取文檔后,可以使用CreateNavigator()
獲取XPathNavigator
對象,該對象可用於查找和更改文檔中的元素。 最后,您可以使用XmlDocument
上的Save()
方法將更改后的文檔寫回。
只需閱讀MSDN上Xml命名空間的文檔即可。 然后,如果您有更具體的問題,請在此處發布...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.