抓取多个节点实例。

huangapple go评论54阅读模式
英文:

Grab multiple instances of a node

问题

我有一个XML文件块在这里。我想要提取所有ToyId的实例并将其放入一个数组中。同时只提取具有"Hastoys = "YES""属性的节点。

<Bookstore Hastoys="YES"> 
  <Authors>7</Authors>
  <Location>Austin TX</Location>
  <Employees>15</Employees>
  <ToyList>
    <ToyId>124</ToyId>
    <ToyId>1251</ToyId>
  </ToyList>
  <ToyList>
    <ToyId>255-2</ToyId>
    <ToyId>6623</ToyID>
  </ToyList>
</Bookstore>
var list =  from r in doc.Descendants("Bookstore")
            .Where(node => (string)node.Attribute("HasToys") == "YES")
            select new
            {
                ToyId = r.Element("ToyList")?.Element("ToyId")?.Value,
            };

我尝试使用上面的查询,但它只返回我ToyId的第一个实例,然后转到下一个块。所以输出将是:124,然后跳过其他ToyId。

英文:

I have a block of an XML file here. I want to grab all the instances of the ToyId and put it in an array. As well as only grab the node with the "Hastoys = "YES"" attribute.

<Bookstore Hastoys="YES"> 
  <Authors>7</Authors>
  <Location>Austin TX</Location>
  <Employees>15</Employees>
  <ToyList>
    <ToyId>124</ToyId>
    <ToyId>1251</ToyId>
  </ToyList>
  <ToyList>
    <ToyId>255-2</ToyId>
    <ToyId>6623</ToyID>
  </ToyList>
</Bookstore>
var list =  from r in doc.Descendants("Bookstore")
            .Where(node => (string)node.Attribute("HasToys") == "YES")
            select new
            {
                ToyId = r.Element("ToyList")?.Element("ToyId")?.Value,
            };

I tried using the query above but its only returning me the first instance of toy id then goes to the next block. So the output would be: 124, and skip the other toyids.

答案1

得分: 2

从您的XML中存在一些问题/顾虑:

1. `<ToyId>` 元素的无效闭合标签为

```xml
&lt;ToyId&gt;6623&lt;/ToyID&gt;
  1. Bookstore 元素中的属性为 "Hastoys"
&lt;Bookstore Hastoys=&quot;YES&quot;&gt; 

但是您的代码中引用的是 "HasToys"

(string)node.Attribute(&quot;HasToys&quot;) == &quot;YES&quot;

方法 1

假设您修复了上述提到的问题,使用 .Descendants(&quot;ToyList&quot;).Elements(&quot;ToyId&quot;) 获取 ToyList 元素下的每个 ToyId 元素。

string xml = @"<Bookstore HasToys=&quot;&quot;YES&quot;&quot;&gt; 
    &lt;Authors&gt;7&lt;/Authors&gt;
    &lt;Location&gt;Austin TX&lt;/Location&gt;
    &lt;Employees&gt;15&lt;/Employees&gt;
    &lt;ToyList&gt;
        &lt;ToyId&gt;124&lt;/ToyId&gt;
        &lt;ToyId&gt;1251&lt;/ToyId&gt;
    &lt;/ToyList&gt;
    &lt;ToyList&gt;
        &lt;ToyId&gt;255-2&lt;/ToyId&gt;
        &lt;ToyId&gt;6623&lt;/ToyId&gt;
    &lt;/ToyList&gt;
&lt;/Bookstore&gt;";

XDocument doc = XDocument.Parse(xml);

var list = (from r in doc.Descendants("Bookstore")
              .Where(node => (string)node.Attribute("HasToys") == "YES")
                .Descendants("ToyList")
                .Elements("ToyId")
              select new
              {
                    ToyId = r.Value,
              });

方法 2

您也可以使用 XPath

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

XmlNode root = doc.DocumentElement;
var list = root.SelectNodes("//Bookstore[@HasToys='YES']/ToyList/ToyId").Cast<XmlNode>()    
    .Select(x => new
              {
                    ToyId = x.InnerText
              })
    .ToList();

<details>
<summary>英文:</summary>

Few issues/concerns from your XML:

1. Invalid closing tag for

<ToyId>6623</ToyID>


2. The attribute in `Bookstore` element is &quot;Hastoys&quot;

<Bookstore Hastoys="YES">


But your code is referring &quot;HasToys&quot;

(string)node.Attribute("HasToys") == "YES"


**Approach 1**

Assume that you fixed the mentioned issues/concerns, working with `.Descendants(&quot;ToyList&quot;).Elements(&quot;ToyId&quot;)` to get each `ToyId` element under the `ToyList` elements.

```csharp
string xml = @&quot;&lt;Bookstore HasToys=&quot;&quot;YES&quot;&quot;&gt; 
    &lt;Authors&gt;7&lt;/Authors&gt;
    &lt;Location&gt;Austin TX&lt;/Location&gt;
    &lt;Employees&gt;15&lt;/Employees&gt;
    &lt;ToyList&gt;
        &lt;ToyId&gt;124&lt;/ToyId&gt;
        &lt;ToyId&gt;1251&lt;/ToyId&gt;
    &lt;/ToyList&gt;
    &lt;ToyList&gt;
        &lt;ToyId&gt;255-2&lt;/ToyId&gt;
        &lt;ToyId&gt;6623&lt;/ToyId&gt;
    &lt;/ToyList&gt;
&lt;/Bookstore&gt;&quot;;

XDocument doc = XDocument.Parse(xml);

var list = (from r in doc.Descendants(&quot;Bookstore&quot;)
              .Where(node =&gt; (string)node.Attribute(&quot;HasToys&quot;) == &quot;YES&quot;)
                .Descendants(&quot;ToyList&quot;)
                .Elements(&quot;ToyId&quot;)
              select new
              {
                    ToyId = r.Value,
              });

Approach 2

You may work with XPath as well

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

XmlNode root = doc.DocumentElement;
var list = root.SelectNodes(&quot;//Bookstore[@HasToys=&#39;YES&#39;]/ToyList/ToyId&quot;).Cast&lt;XmlNode&gt;()    
    .Select(x =&gt; new
              {
                    ToyId = x.InnerText
              })
    .ToList();

huangapple
  • 本文由 发表于 2023年5月17日 13:00:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76268703.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定