Linq XML - 使用父节点和子节点的组合获取不同的值



我做了一个Linq语句,希望接收XML文件的所有节点。

foreach (var node in epaXmlLoad.Root.Descendants()
                                    .DescendantNodes()
                                    .OfType<XElement>()
                                    .Distinct())
{
    newEntity = true;
    xmlModel.Node = node.Name.ToString();
    xmlModel.ParentNode = node.Parent.Name.ToString();
    model.Save(xmlModel);
}

这将保存节点和该节点的父节点在一个表中。

但是当我运行这个时,表中会有重复的数据。我无法区分节点值,只是因为有更多的子节点具有相同的名称,但在它们上面有其他父节点。

<EPC>
<General>
    <Input>3</Invoer>
    <Amount>3</Amount>
    <Name>Bla</Name>
</General>
<Sectors>
    <Sector>
        <Name>Blalbla</Perc>
        <UsageID>0</UsageID>
        <Detection>0</Detection>
    <Sector>
    <Sector>
        <Name>Blalbla</Perc>
        <UsageID>0</UsageID>
        <Detection>0</Detection>
    <Sector>
<Sectors>
<Devices>
    <Device>
        <Name>Bladiebla</name>
        <Amount>5</Amount>
        <Detection>True</Detection>
    </Device>
    <Device>
        <Name>Bladiebla2</name>
        <Amount>5</Amount>
        <Detection>True</Detection>
    </Device>
<Devices>

^这个XML描述了我的问题

虽然您的问题对预期结果不是很清楚,但似乎您正在尝试从XML中删除重复节点。

XML:

<Parent>
  <Child>
    <Value>42</Value>
  </Child>
  <Child>
    <Value>stackoverflow</Value>
  </Child>
  <Child>
    <Value>stackoverflow</Value>
    <Grandchild>17</Grandchild>
  </Child>
  <Child>
    <Value>42</Value>
  </Child>
</Parent>

应转换为:

<Parent>
  <Child>
    <Value>42</Value>
  </Child>
  <Child>
    <Value>stackoverflow</Value>
  </Child>
  <Child>
    <Value>stackoverflow</Value>
    <Grandchild>17</Grandchild>
  </Child>
</Parent>

这需要对整个树进行递归比较。在元素上使用Distinct将会失败,因为它没有考虑到子元素。

public static XElement Reduce(XElement root)
{
    XElement result = new XElement(root.Name);
    result.Add(root.Nodes().OfType<XText>());
    List<XElement> children = new List<XElement>();
    foreach (var child in root.Elements())
    {
        var reducedChild = Reduce(child);
        if (!children.Any(c => IsDuplicate(c, reducedChild)))
        {
            children.Add(reducedChild);
        }
    }
    result.Add(children);
    return result;
}
public static bool IsDuplicate(XElement element1, XElement element2)
{
    if (element1.Name != element2.Name || element1.Value != element2.Value)
    {
        return false;
    }
    var children1 = element1.Elements();
    var children2 = element2.Elements();
    if (children1.Count() != children2.Count())
    {
        return false;
    }
    return children1.Zip(children2, (c1, c2) => IsDuplicate(c1, c2)).All(isDup => isDup);
}

XDocument的根上调用Reduce将构建一个具有不同元素的新XElement。现在可以将所有节点添加到模型中。

请注意,这并没有考虑属性。还要注意,这可能不是最有效的算法。

顺便说一句:您的示例XML充满了错误(标签没有正确关闭)。

最新更新