【问题标题】:How to differentiate between two exactly same elements at different parent hierarchy in xml using XDocument如何使用 XDocument 区分 xml 中不同父层次结构中的两个完全相同的元素
【发布时间】:2013-02-01 13:52:02
【问题描述】:

我有一个类似如下的 xml:

<return>
  <exams>
    <remove>
    </remove>
    <add>
        <exam errorCode="0" examRef="1" />
    </add>
    <add>
        <exam errorCode="0" examRef="1" />
        <exam errorCode="0" examRef="1" />
    </add>
  </exams>
</return>

我正在构建一个实用程序,该实用程序可以通过提取其祖先层次结构来区分每个节点。例如:

return[0].exams[0].add[0].exam[0] //This indicates the first exam node in the first add element.
return[0].exams[0].add[1].exam[0] //This indicates the first exam node in the second add element.
return[0].exams[0].add[1].exam[1] //This indicates the second exam node in the second add element.

等等。我到目前为止的代码是:

    private string GetAncestorNodeAsString(XElement el)
    {
        string ancestorData = string.Empty;

        el.Ancestors().Reverse().ToList().ForEach(anc =>
        {
            if (ancestorData == string.Empty)
            {
                ancestorData = String.Format("{0}[0]", anc.Name.ToString());
            }
            else
            {
                ancestorData = String.Format("{0}.{1}[0]", ancestorData, anc.Name.ToString());
            }
        });

        if (ancestorData == string.Empty)
        {
            ancestorData = el.Name.ToString();
        }
        else
        {
            ancestorData = String.Format("{0}.{1}[0]", ancestorData, el.Name.ToString());
        }
        return ancestorData;
    }

此代码返回如下内容:

return[0].exams[0].add[0].exam[0] //zeros here are hardcoded in the code and I need some mechanism to get the position of each of the element in the xml.

我可以建立以下元素的位置:

            var elements = el.Elements().Select((e, index) => new
            {
                node = e,
                position = index
            });

但这只会给我一个元素中只有直接子元素的位置。我需要识别所有祖先及其在 xml 中的位置。

有人可以帮忙吗?

【问题讨论】:

    标签: c# .net xml linq linq-to-xml


    【解决方案1】:

    这里是返回元素索引的方法:

    private int GetElementIndex(XElement e)
    {
        return e.NodesBeforeSelf().OfType<XElement>().Count(x => x.Name == e.Name);
    }
    

    还有你修改​​过的代码。请记住 - 我使用 AncestorsAndSelf 来使用单循环。我也避免创建元素列表。并使用StringBuilder 聚合结果并避免创建字符串。

    private static string GetAncestorNodeAsString(XElement e)
    {
        return e.AncestorsAndSelf().Reverse()
                .Aggregate(
                   new StringBuilder(),
                   (sb, a) => sb.AppendFormat("{0}{1}[{2}]", 
                              sb.Length == 0 ? "" : ".", a.Name, GetElementIndex(a)),
                   sb => sb.ToString());
    }
    

    【讨论】:

    • 谢谢。这是一个漂亮的代码并且非常高效。我从 2 天以来一直在寻找这个 :) 赞赏。
    【解决方案2】:

    使用递归方法:

    private static string GetAncestorNodeAsString(XElement el)
    {
        if (el.Parent == null)
            return String.Format("{0}[0]", el.Name.LocalName);
        else
            return String.Format("{0}.{1}[{2}]", 
                GetAncestorNodeAsString(el.Parent), 
                el.Name.LocalName, 
                el.ElementsBeforeSelf().Count(e => e.Name == el.Name));
    }
    

    【讨论】:

    • +1 也可以将您标记为答案,但您的代码出现在已回答的代码之后:(但无论如何谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多