繁体   English   中英

使用 C# 从 XML 中检索文本

[英]Retrieving text from XML with C#

我有一个包含以下内容的文本文件:

<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>

我想检索标签之间的所有值例如,在列表中,我想检索和

我怎么能这样做?

我试过这个:

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 什么都不包含

你能帮助我吗? 谢谢你。

由于您的文件具有 XML 格式,因此您可以使用XmlSerializer来读取它,这比手动解析要轻松

首先创建一个Person类(或在 Visual Studio 中使用Edit -> Paste special -> Paste XML as classes 生成

[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()方法来获取对象所需的字符串表示

如果您只需要这些值作为纯文本。 您可以使用正则表达式或 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 次操作收集一次

分配:每个操作分配的内存(仅限托管,包括,1KB = 1024B)

所以,答案是:取决于你需要对结果做什么。 我希望我能帮助你做出决定。

此致

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM