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

tri*_*ati 3 c# xml xml-parsing

我有一个 long 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>
Run Code Online (Sandbox Code Playgroud)

我的代码是这样的,但出现错误;

 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");
            }
Run Code Online (Sandbox Code Playgroud)

我目前遇到投射错误,我不知道我的这段代码会根据我的意愿给我结果。

错误:

附加信息:无法将类型为“WhereEnumerableIterator`1[System.Xml.Linq.XElement]”的对象转换为类型“System.Xml.Linq.XElement”。

Nko*_*osi 5

错误是因为您试图将 LinqWhere结果重新分配给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();
Run Code Online (Sandbox Code Playgroud)

entries 应仅包含与提供的子元素过滤器匹配的所需父元素。

上面的方法是根据父节点搜索子节点的。

下面的方法先找到子节点,然后在树中查找父节点

List<XElement> entries = elements
    .Descendants(childNode)
    .Where(child => child.Value == childNodeValue)
    .SelectMany(child => child.Ancestors(parentNode))
    .ToList();
Run Code Online (Sandbox Code Playgroud)

两种方法都基于以下 XML 生成相同的 2 个匹配元素结果

var xml = @"
<sdnList>
    <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>

    <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>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>
</sdnList>
";
Run Code Online (Sandbox Code Playgroud)