0

私は次のような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内でのその位置を特定する必要があります。

誰か助けてもらえますか?

4

2 に答える 2

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());
}
于 2013-02-01T14:09:33.937 に答える
1

再帰的な方法を使用します。

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));
}
于 2013-02-01T14:13:20.367 に答える