根据c#LINQ中的子节点XML获取特定的父节点

时间:2018-05-04 05:12:25

标签: c# xml xml-parsing

我有一个长XML,其父节点为sdnEntry,每个父节点都有其子sdnType,用于定义条目的类型。 我正在尝试只获取sdnTypeIndividual的节点。

我的xml的简短样本在这里;

<sdnEntry>
    <uid>6905</uid>
    <lastName>abc</lastName>
    <sdnType>Entity</sdnType> // type is entity

    <akaList>
    <aka>
        <uid>4741</uid>
        <type>a.k.a.</type>
        <category>strong</category>
        <lastName>ABC</lastName>
        <firstName>ABCCCC</firstName>
    </aka>
    <aka>
        <uid>4742</uid>
        <type>a.k.a.</type>
        <category>weak</category>
        <lastName>ADCS</lastName>
    </aka>
    </akaList>

    <nationalityList>
        <nationality>
        <uid>5416</uid>
        <country>XYZ</country>
        <mainEntry>true</mainEntry>
        </nationality>
    </nationalityList>
</sdnEntry>

<sdnEntry>
    <uid>6905</uid>
    <lastName>abc</lastName>
    <sdnType>Individual</sdnType> // type is individual

    <akaList>
    <aka>
        <uid>4741</uid>
        <type>a.k.a.</type>
        <category>strong</category>
        <lastName>ABC</lastName>
        <firstName>ABCCCC</firstName>
    </aka>
    <aka>
        <uid>4742</uid>
        <type>a.k.a.</type>
        <category>weak</category>
        <lastName>ADCS</lastName>
    </aka>
    </akaList>

    <nationalityList>
        <nationality>
        <uid>5416</uid>
        <country>XYZ</country>
        <mainEntry>true</mainEntry>
        </nationality>
    </nationalityList>
</sdnEntry>

<sdnEntry>
    <uid>6905</uid>
    <lastName>abc</lastName>
    <sdnType>Individual</sdnType>

    <akaList>
    <aka>
        <uid>4741</uid>
        <type>a.k.a.</type>
        <category>strong</category>
        <lastName>ABC</lastName>
        <firstName>ABCCCC</firstName>
    </aka>
    <aka>
        <uid>4742</uid>
        <type>a.k.a.</type>
        <category>weak</category>
        <lastName>ADCS</lastName>
    </aka>
    </akaList>

    <nationalityList>
        <nationality>
        <uid>5416</uid>
        <country>XYZ</country>
        <mainEntry>true</mainEntry>
        </nationality>
    </nationalityList>
</sdnEntry>

<sdnEntry>
    <uid>6905</uid>
    <lastName>abc</lastName>
    <sdnType>Entity</sdnType>

    <akaList>
    <aka>
        <uid>4741</uid>
        <type>a.k.a.</type>
        <category>strong</category>
        <lastName>ABC</lastName>
        <firstName>ABCCCC</firstName>
    </aka>
    <aka>
        <uid>4742</uid>
        <type>a.k.a.</type>
        <category>weak</category>
        <lastName>ADCS</lastName>
    </aka>
    </akaList>

    <nationalityList>
        <nationality>
        <uid>5416</uid>
        <country>XYZ</country>
        <mainEntry>true</mainEntry>
        </nationality>
    </nationalityList>
</sdnEntry>

我的代码是这样的,但我收到错误;

 var lXelements = XElement.Parse(xml);
 var lParentNode = "sdnEntry";
  if (lParentNode == "sdnEntry")
            {
 //lXelements = (XElement)lXelements.Descendants("sdnType").Where(x => x.Name.LocalName == "Individual");
                lXelements = (XElement)lXelements.Descendants("sdnType").Where(x => (string)x.Value == "Individual");
            }

我目前正在收到投射错误,我不会根据自己的意愿给出结果。

错误:

  

附加信息:无法投射类型的对象   &#39; WhereEnumerableIterator`1 [System.Xml.Linq.XElement]&#39;输入   &#39; System.Xml.Linq.XElement&#39;

3 个答案:

答案 0 :(得分:4)

该错误是因为您尝试将Linq shared_ptr结果重新分配给weak_ptr

除此之外,您基本上希望获得有孩子的所有Where个节点XElement

<sdnEntry>

<sdnType>Individual</sdnType>应仅包含与提供的子元素过滤器匹配的所需父元素。

上述方法基于父节点搜索子节点。

以下方法首先查找子节点,然后在树中查找父节点

XElement elements = XElement.Parse(xml);
var parentNode = "sdnEntry";
var childNode = "sdnType";
var childNodeValue = "Individual";
List<XElement> entries = elements
    .Descendants(parentNode)
    .Where(parent => parent.Descendants(childNode)
        .Any(child => child.Value == childNodeValue)
    ).ToList();

两种方法基于以下XML

生成相同的2个匹配元素
entries

答案 1 :(得分:1)

您可以尝试以下操作,看看它是否对您有所帮助:这不使用lambda表达式,但与上面的Nkosi代码相同

    File "/opt/envDjango/lib/python3.5/site-packages/celery/app/task.py", line 518, in apply_async
    check_arguments(*(args or ()), **(kwargs or {}))
    TypeError: functools.partial object argument after ** must be a mapping, not int

答案 2 :(得分:0)

您正在尝试将IEnumerable<XElement>投射到XElement。带走演员,它应该工作:

lXelements = lXelements.Descendants("sdnType")
          .Where(x => (string)x.Value == "Individual");

...

foreach(var element in lXelements)
{
   DoSomething(element);
}