使用 C# 从 XML 中检索文本
Posted
技术标签:
【中文标题】使用 C# 从 XML 中检索文本【英文标题】:Retrieving text from XML with C# 【发布时间】:2020-04-07 15:50:52 【问题描述】:我有一个包含以下内容的文本文件:
<Person>
<Prenom>Jack</Prenom>
<Nom>Jhon</Nom>
<Adresse>4 rue de la Mélandine</Adresse>
<Tél></Tél>
<Email>email@gmail.com</Email>
<PhotoPath>c:\Program Files\Zonedetec\Gestionnaire de tâche v2\Img\5295f1ea-372a-4f2f-8f32-c52e8a48cc0839105.png</PhotoPath>
<Age>19</Age>
<Id>4640434</Id>
</Person>
<Person>
<Prenom>Jean</Prenom>
<Nom>Delamar</Nom>
<Adresse>13 rue de la Mélandine</Adresse>
<Tél></Tél>
<Email>email@gmail.com</Email>
<PhotoPath>c:\Program Files\Zonedetec\Gestionnaire de tâche v2\Img\5295f1ea-372a-4f2f-8f32-c52e8a48cc0839105.png</PhotoPath>
<Age>19</Age>
<Id>4640434</Id>
</Person>
我想检索标签之间的所有值 例如,在一个列表中,我想检索和
之间的值(这里是 2)我该怎么做?
我试过了:
internal static void LoadPerson()
string data = File.ReadAllText(Main.PersonnePath);
Regex regex = new Regex("<Person>(.*)</Person>");
var v = regex.Match(data);
string s = v.Groups[1].ToString();
MessageBox.Show(s);
除了 s 什么都不包含
你能帮帮我吗? 谢谢你。
【问题讨论】:
Person
标签之间有两个以上的值。您的文件是纯 XML 文件,您可以使用 XmlSerializer
并将您的 xml 反序列化为对象以获取任何字符串而不是
你为什么要从我身边夺走我的你好?没有资格打招呼?
正如@PavelAnikhouski 所说,您需要使用XmlSerializer
-> docs.microsoft.com/en-us/dotnet/api/…
@PavelAnikhouski 的答案是正确的,只是它在这里不起作用,因为您的 XML 不正确。它有两个 Person 标签,但它们必须是一个根标签。所以 XMLSerializer 会失败。如果它只是示例并且原始文件具有像<persons>
这样的包装标签,那么 XMLSerializer 将起作用。
@SumitGupta 我同意你的看法。也许他不知道 XML 是什么。因此,我在回答中解释了两种方式。我也赞成 Pavel 的回答,因为它提供了非常好的使用 C# 处理 XML 的信息。
【参考方案1】:
如果您只需要将此值作为纯文本。您可以使用正则表达式或 XMLSerializer 或 (Linq to XML)。
在选择一种或另一种方法之前,您需要分析的是:
1) 我需要做什么?
1.a) 如果您只需要每个标签内的纯文本。而且你不会做任何验证/计算/重新解析器。您可以轻松地使用这两种方法。
1.a.1) 使用正则表达式:
public List<string> GetValueByRegex(string input)
string pattern = @"<Person>([\s\S]*?)</Person>";
var matches = Regex.Matches(input, pattern);
if (matches.All(m => !m.Success))
return null;
var result = new List<string>();
foreach (Match match in matches)
result.Add(match.Groups[1].Value);
return result;
1.a.2) 使用 XDocument 解析 Xml 字符串
重要提示:XDocument 要求您的 XML 有一个根标签才能工作。因为您的 XML 有两个根标签。我用字符串插值强制它
$"<root>input</root>"
public List<string> GetValueByXmlParse(string input)
var result = new List<string>();
var ensureThereAreOnlyOneRootTag = $"<root>input</root>";
XDocument xmlDocument = XDocument.Parse(ensureThereAreOnlyOneRootTag);
foreach(var personXml in xmlDocument.Root.Elements("Person"))
result.Add(String.Concat(personXml.Nodes()));
return result;
1.b) 如果您将对从 XML 中提取的数据做任何事情,最好将其解析为对象。
您可以通过复制 XML 值并单击“编辑”>“选择性粘贴”>“将 XML 粘贴为类”来使 Visual Studio 生成一个。
@PavelAnikhouski 已经分享了一个很好的例子。
2) 我真的需要一个好的表现吗?
回答我使用 Benchmark nuget 包来比较所有选项。结果如下:
| Method | Gen 0 | Allocated |
|---------------------- |---------:|----------:|
| GetValueByRegex | 1.2207 | 2688 B |
| GetValueByXmlParse | 115.6006 | 243536 B |
第 0 代:GC 第 0 代每 1000 次操作收集一次
Allocated :为每个操作分配的内存(仅限托管,含,1KB = 1024B)
所以,答案是:取决于你需要对结果做什么。我希望我能帮助你做出决定。
最好的问候
【讨论】:
您好,非常感谢您这么详细的回答!你真的让我明白了,一切正常! 欢迎。很高兴我能提供帮助。【参考方案2】:由于您的文件是 XML 格式,您可以使用 XmlSerializer
来读取它,这比手动解析它不那么痛苦
首先创建一个Person
类(或在Visual Studio 中使用编辑-> 选择性粘贴-> 将XML 粘贴为类 生成)
[Serializable]
public class Person
private string _prenomField;
private string _nomField;
private string _adresseField;
private object _télField;
private string _emailField;
private string _photoPathField;
private byte _ageField;
private uint _idField;
public string Prenom
get => _prenomField;
set => _prenomField = value;
public string Nom
get => _nomField;
set => _nomField = value;
public string Adresse
get => _adresseField;
set => _adresseField = value;
public object Tél
get => _télField;
set => _télField = value;
public string Email
get => _emailField;
set => _emailField = value;
public string PhotoPath
get => _photoPathField;
set => _photoPathField = value;
public byte Age
get => _ageField;
set => _ageField = value;
public uint Id
get => _idField;
set => _idField = value;
比稍微更新文件结构(你必须有一个根标签)
<?xml version="1.0" encoding="utf-8" ?>
<people>
<Person>
<Prenom>Jack</Prenom>
<Nom>Jhon</Nom>
<Adresse>4 rue de la Mélandine</Adresse>
<Tél></Tél>
<Email>email@gmail.com</Email>
<PhotoPath>c:\Program Files\Zonedetec\Gestionnaire de tâche v2\Img\5295f1ea-372a-4f2f-8f32-c52e8a48cc0839105.png</PhotoPath>
<Age>19</Age>
<Id>4640434</Id>
</Person>
<Person>
<Prenom>Jean</Prenom>
<Nom>Delamar</Nom>
<Adresse>13 rue de la Mélandine</Adresse>
<Tél></Tél>
<Email>email@gmail.com</Email>
<PhotoPath>c:\Program Files\Zonedetec\Gestionnaire de tâche v2\Img\5295f1ea-372a-4f2f-8f32-c52e8a48cc0839105.png</PhotoPath>
<Age>19</Age>
<Id>4640434</Id>
</Person>
</people>
最后解析它
var mySerializer = new XmlSerializer(typeof(Person[]), new XmlRootAttribute("people"));
Person[] people;
using (var fileStream = new FileStream(Main.PersonnePath, FileMode.Open))
people = (Person[])mySerializer.Deserialize(fileStream);
不要忘记添加 using System.Xml.Serialization;
命名空间。反序列化后people
数组将包含您需要的所有值,您可以将它们格式化为任何字符串/任何您想要的。这里最好的选择是覆盖Person
类的ToString()
方法以获得所需的对象字符串表示
【讨论】:
以上是关于使用 C# 从 XML 中检索文本的主要内容,如果未能解决你的问题,请参考以下文章