温馨提示:本文翻译自stackoverflow.com,查看原文请点击:c# - Get element by type XDocument
c# xml linq-to-xml

c# - 通过XDocument类型获取元素

发布于 2020-03-31 23:23:46

如何使用XDocument找到以下结构的正确元素?

XML:

    <Body xmlns="http://tempuri.org/body" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <Address>
            <Segment i:type="AddressSegment">
                <Id>9999</Id>
             </Segment>
        </Address>
        <Segmentation>
            <Segment xmlns:d4p1="http://tempuri.org/foo" i:type="d4p1:FooSegment">
                <d4p1:Id>63</d4p1:Id>
            </Segment>
            <Segment xmlns:d4p1="http://tempuri.org/bar" i:type="d4p1:BarSegment">
                <d4p1:Id>159</d4p1:Id>
            </Segment>
            <Segment i:type="BasicSegment">
                <Id>10</Id>
            </Segment>
        </Segmentation>
    </Body>

C#:

using ConsoleApp1.Properties;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var xDoc = XDocument.Parse(Resources.XmlDoc);
            var dataSegments = xDoc.Descendants(XName.Get("Segment", "http://tempuri.org/body")).ToList();
            Console.ReadLine();
        }
    }
}

这将导致我列表中的所有Segment元素。但是,如果我只想选择Foo和Bar元素怎么办?如何查找元素的i:type?

查看更多

提问者
grmihel
被浏览
99
Krishna Muppalla 2020-01-31 22:20

输入XML。更正了名称空间。

<?xml version="1.0" encoding="utf-8" ?>
<Body xmlns:i="http://tempuri.org/body">
  <Address>
    <Segment i:type="AddressSegment">
      <Id>9999</Id>
    </Segment>
  </Address>
  <Segmentation>
    <Segment xmlns:d4p1="http://tempuri.org/foo" i:type="d4p1:FooSegment">
      <d4p1:Id>63</d4p1:Id>
    </Segment>
    <Segment xmlns:d4p1="http://tempuri.org/bar" i:type="d4p1:BarSegment">
      <d4p1:Id>159</d4p1:Id>
    </Segment>
    <Segment i:type="BasicSegment">
      <Id>10</Id>
    </Segment>
  </Segmentation>
</Body>

使用xmltocsharp为FooSegment和BooSegment创建了模型类

[XmlRoot(ElementName = "Segment")]
public class FooSegment
{
    [XmlElement(ElementName = "Id", Namespace = "http://tempuri.org/foo")]
    public List<string> Id { get; set; }
    [XmlAttribute(AttributeName = "d4p1", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string D4p1 { get; set; }
    [XmlAttribute(AttributeName = "type", Namespace = "http://tempuri.org/body")]
    public string Type { get; set; }
}

[XmlRoot(ElementName = "Segment")]
public class BarSegment
{
    [XmlElement(ElementName = "Id", Namespace = "http://tempuri.org/bar")]
    public List<string> Id { get; set; }
    [XmlAttribute(AttributeName = "d4p1", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string D4p1 { get; set; }
    [XmlAttribute(AttributeName = "type", Namespace = "http://tempuri.org/body")]
    public string Type { get; set; }
}

使用此模型使用XmlSerializer反序列化

XDocument xml = XDocument.Load("1.xml");
XNamespace ns = "http://tempuri.org/body";

string[] values = new string[] { "d4p1:FooSegment", "d4p1:BarSegment" };
var result = xml.Root.DescendantsAndSelf("Segment")
    .Where(r => values.Contains((string)r.Attribute(ns + "type").Value));

foreach (var nodeValue in result)
{
    if(nodeValue.Attribute(ns + "type").Value.ToString() == "d4p1:FooSegment")
    {
        var fooObject = (FooSegment)new XmlSerializer(typeof(FooSegment)).Deserialize(new StringReader(nodeValue.ToString()));
        Console.WriteLine($"{fooObject.Id[0]}");
    }
    else
    {
        var barObject = (BarSegment)new XmlSerializer(typeof(BarSegment)).Deserialize(new StringReader(nodeValue.ToString()));
        Console.WriteLine($"{barObject.Id[0]}");
    }                
}

输出量

63
159