如何在c#中获取xml父元素中的所有子元素

时间:2016-01-22 07:23:51

标签: c# .net xml linq-to-xml

认为这是我的xml ..

<ListOfDestinations>
  <Destination>
    <City>Ahmedabad</City>
    <Title>Cheap Flights to Ahmedabad</Title>
    <Content>
    <Top10PlacestoVisit>
      <subTitle>1</subTitle>
      <details>d1</details>
      <subTitle>2</subTitle>
      <details>d2</details>
      <subTitle>3</subTitle>
      <details>d3</details>
      <subTitle>4</subTitle>
      <details>d4</details>
      <subTitle>5</subTitle>
      <details>d5</details>
      <subTitle>6</subTitle>
      <details>d6</details>
      <subTitle>7</subTitle>
      <details>d7</details>
      <subTitle>8</subTitle>
      <details>d8</details>
      <subTitle>9</subTitle>
      <details>d9</details>
      <subTitle>10</subTitle>
      <details>d10</details>
    </Top10PlacestoVisit>
    </Content>
   </Destination>
 </ListOfDestinations>

所以我希望将所有subTitledetails放到列表中。我可以这样做。这就是我尝试过的。

XmlDocument DestinationXml = new XmlDocument();
DestinationXml.Load(Server.MapPath("~/Xml_Data/Destination.xml"));
var xdoc = XDocument.Parse(DestinationXml.InnerXml);


var selectedCity = xdoc.Descendants("ListOfDestinations")
                        .Select(d => d.Elements("Destination")
                        .Where(w => w.Element("City").Value == DesName));

在这个地方获取<Top10PlacestoVisit></Top10PlacestoVisit>

内的所有数据(子标题和详细信息)

然后我创建了一个Model并分配了这样的值。但我无法立即将subTitledetails添加到列表中。这是我尝试的内容

foreach (var itemz in selectedCity)
{
    var needed = itemz.Elements("Top10PlacestoVisit");
    foreach (var nitems in needed)
   {
       var getSubs = needed.Elements("details");
       foreach (var itm in getSubs)
       {
           details.Add(new Destinations
          {
               details = itm.Value
         });
       }
  }
}

ViewBag.details = details;

在这里它成功获得了subTitle但是如何获得details并在同一时间分配它。请帮助我。

3 个答案:

答案 0 :(得分:1)

你的xml结构不太好看。从我的观点来看,将subTitledetails相关的内容放入一些封闭的父元素中是合理的:

<Top10PlacestoVisit>
    <Place>
      <subTitle>1</subTitle>
      <details>d1</details>
    </Place>

无论如何,如果你与你发布的结构捆绑在一起并且无法改变它 - 你仍然可以实现你的目标:

var details = xdoc.XPathSelectElements(
       string.Format("/ListOfDestinations/Destination[City='{0}']/Content/Top10PlacestoVisit/details", DesName))
    .Select(d => new { subTitle = (d.PreviousNode as XElement).Value, details = d.Value})
    .ToList();

请注意,使用XPathSelectElementsdetails方式收集.Select(d => new { subTitle = (d.PreviousNode as XElement).Value, details = d.Value}) 是我个人的偏好,无论如何你都可以这样做。这里的关键想法是:

details

关于PreviousNode元素的集合。因此,您只需使用XElement的{​​{1}}属性访问上一个兄弟元素,并且对于每个details元素,它恰好与其相关subTitle

答案 1 :(得分:1)

如果您坚持使用XML,那么您可以通过使用以下内容来假设结构来实现:

var topPlacesForCity = doc.Descendants("Destination")
    .Where(x => (string) x.Element("City") == "Ahmedabad")
    .Descendants("Top10PlacestoVisit")
    .Elements("subTitle")
    .Select(subTitle => new
    {
        SubTitle = subTitle.Value,
        Details = (string) subTitle.ElementsAfterSelf("details").First()
    });

如果您在评论中提到,您可以将其更改为包含父Place元素,那么它会更加强大和明显:

var topPlacesForCity = doc.Descendants("Destination")
    .Where(x => (string) x.Element("City") == "Ahmedabad")
    .Descendants("Top10PlacestoVisit")
    .Elements("Place")
    .Select(place => new
    {
        SubTitle = (string) place.Element("subTitle"),
        Details = (string) place.Element("details")
    });

顺便说一句,没有理由将XML加载到XmlDocument中,然后直接将其解析为XDocument并将其丢弃。请改用XDocument.Load(Server.MapPath("..."))

答案 2 :(得分:0)

尝试这样做,将subTitle Attribute添加为details标记,如下所示

<Top10PlacestoVisit>

  <details subTitle ="place01">d1</details>

</Top10PlacestoVisit>

然后这样称呼它。

XElement xe = XElement.Load(Server.MapPath("your path"));

            var check = xe.Descendants("Destination")
                        .Where(n => n.Element("City").Value == "Ahmedabad")
                        .Select(l => l.Element("Top10PlacestoVisit"));

            List<someList> dst = new List<someList>();
          foreach (var item in check)
          {
              var subs = item.Elements("details");
              foreach(var item1 in subs)
              {
                  dst.Add(new someList 
                  {
                      detail = item1.Value,
                      subtitle = item1.Attribute("subTitle").Value

                  });
              }
          }

          ViewBag.all = dst;