簡體   English   中英

使用C#中的Linq to XML在文檔中搜索不同的XML結構

[英]Searching for distinct XML structures in a document with Linq to XML in C#

我已經編寫了一些C#來解析XML文檔中的許多元素,並僅返回那些具有不同子結構的元素中的第一個? 例如,如果我有以下XML文檔,則對rootElement.DistinctStructures("base")的調用返回一個IEnumerable<XElement> ,該IEnumerable<XElement>僅包含ID為1、3和5的基本元素。

<root>
    <base id="1">
        <a>text</a>
    </base>
    <base id="2">
        <a>more text</a>
    </base>
    <base id="3">
        <b>text</b>
    </base>
    <base id="4">
        <a>other text</a>
    </base>
    <base id="5">
        <a>
            <c>sub text</c>
        </a>
    </base>
</root>

基本代碼從結構中的元素名稱和文本節點生成唯一鍵,並將它們與保存的唯一元素集合進行比較。 我的問題是這樣做是否有更整潔的方法?

private Dictionary<string, XElement> uniqueElements = new Dictionary<string, XElement>();

public void Go()
{
    foreach (var entry in xmlDoc.Elements("e"))
    {
        string keyString = AsStructureString(entry).ToString();
        if (!uniqueElements.Keys.Contains(keyString))
        {
            uniqueElements.Add(keyString, entry);
        }
    }
}

public StringBuilder AsStructureString(this XElement input)
{
    StringBuilder sb = new StringBuilder(input.Name.LocalName);

    var NodesOfNote = input.Nodes().Where(n => n.NodeType == XmlNodeType.Element || n.NodeType == XmlNodeType.Text).ToList();

    if (NodesOfNote.Any())
    {
        sb.Append(">>");
    }

    foreach (var childNode in NodesOfNote)
    {
        if (childNode.NodeType == XmlNodeType.Element)
        {
            sb.Append((childNode as XElement).AsStructureString());
        }
        if (childNode.NodeType == XmlNodeType.Text)
        {
            sb.Append("txt");
        }
        if (!childNode.IsLastIn(NodesOfNote))
        {
            sb.Append("|");
        }
    }

    return sb;
}

這可能比您想象的要容易。 如果決定節點結構的是其元素和文本(與內容無關),則可以執行以下操作:

IEnumerable<XElement> DistinctStructures(XContainer root, XName name)
{
    return
        from d in root.Descendants(name)
        group d by GetKey(d) into g
        select g.First();

    string GetKey(XElement n) =>
        String.Join(",",
            n.DescendantNodes().Select(d =>
                d is XElement e ? $"{e.Name}^{GetDepth(e)}"
                : d is XText t ? $"<text>^{GetDepth(t)}"
                : default
            )
        );
    int GetDepth(XObject o)
    {
        var depth = 0;
        for (var c = o; c != null; c = c.Parent)
            ++depth;
        return depth;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM