我的计划是使用我的C#程序读取XML文档,搜索我想要更改的特定条目,然后写出修改后的文档。但是,我已经变得不稳定,因为很难区分元素,无论它们是使用XmlTextReader开始还是结束,我正在使用它来读取文件。我可以提出一些建议,让我走上正轨。
该文档是一个HTML文档,您可以想象,它非常复杂。
我想在HTML文档中搜索元素id,例如查找并更改src;
<img border="0" src="bigpicture.png" width="248" height="36" alt="" id="lookforthis" />
答案 0 :(得分:30)
如果它实际上是有效的XML,并且很容易适合内存,我每次都会选择LINQ to XML(XDocument
,XElement
等。它是迄今为止我用过的最好的XML API。它很容易形成查询,也很容易构建新元素。
您可以在适当的位置使用XPath,或使用内置轴方法(Elements()
,Descendants()
,Attributes()
等)。如果您能告诉我们您遇到的具体问题,我很乐意帮助您了解如何在LINQ to XML中表达它们。
另一方面,如果这是不是有效XML的HTML,那么您将面临更加艰难的时间 - 因为XML API通常希望使用有效的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");
}
答案 1 :(得分:4)
您处理的文件相对较小吗?如果是这样,您可以使用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的结构,这可以使您的解析代码更简单。
答案 2 :(得分:2)
这是我编写的用于修改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>
答案 3 :(得分:1)
如果您的小文档适合计算机内存,则可以使用XmlDocument
。
否则,您可以使用XmlReader
来遍历文档。
使用XmlReader
您可以使用以下方法找到元素类型:
while (xml.Read()) {
switch xml.NodeType {
case XmlNodeType.Element:
//Do something
case XmlNodeType.Text:
//Do something
case XmlNodeType.EndElement:
//Do something
}
}
答案 4 :(得分:1)
对于手头的任务 - (以正式方式阅读现有文档,编写和修改),我将XPathDocument使用XslCompiledTransform。
如果你不能正式化,没有预先存在的文档或者通常需要更多的自适应逻辑,我会像Skeet所说的那样使用LINQ和XDocument。
基本上如果任务是转换然后是XSLT,如果任务是操作那么LINQ。
答案 5 :(得分:1)
我最喜欢的工具是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');
答案 6 :(得分:0)
一种相当简单的方法是创建一个新的XmlDocument
,然后使用Load()
方法填充它。获得文档后,可以使用CreateNavigator()
获取可用于查找和更改文档中元素的XPathNavigator
对象。最后,您可以使用Save()
上的XmlDocument
方法将已更改的文档写回。
答案 7 :(得分:-1)
首先阅读Xml namespace on the MSDN的文档。如果您有更具体的问题,请在此处发布...