0

私は書いた:

        public string GetOutline(int indentLevel, XElement element)
        {
        StringBuilder result = new StringBuilder();


        result = result.AppendLine(new string('-', indentLevel * 2) + element.Name);

        foreach (var childElement in element.Elements())
        {
            result.Append(GetOutline(indentLevel + 3, childElement));
        }

        return result.ToString();
    }

xmlファイルでこの再帰的な方法を実行した結果は次のとおりです。

    Videos
    ------Video
    ------------Title
    ------------Director
    ------------Actors
    ------------------Actor
    ------------------Actor
    ------------------Actor
    ------------------Actor
    ------------Length
    ------------Format
    ------------Rating
    ------Video
    ------------Title
    ------------Director
    ------------Length
    ------------Format
    ------------Rating
enter code here

しかし、私は出力を以下のようにしたいと思います:

    Videos
    ------Video
    ------------Title
    ------------Director
    ------------Actors
    ------------------Actor
    ------------Length
    ------------Format
    ------------Rating

コードを編集する方法は?昨日から本当にこれに苦労しています...

4

3 に答える 3

1

名前によるlinqグループ化を使用します。

foreach (var childElement in element.Elements().GroupBy(childElement => childElement.Name))
{
    result.Append(GetOutline(indentLevel + 3, childElement.First()));
}

それ以外の:

foreach (var childElement in element.Elements())
{
    result.Append(GetOutline(indentLevel + 3, childElement.First()));
}

この方法の唯一の問題は、の使用ですFirst。たとえば、XMLファイルに次のようなものがある場合:

<actors>
    <actor>
        <property/>
    </actor>
    <actor>
        <differentProperty/>
        <differentProperty2/>
    </actor>
</actors>

グループ化するとFirst、結果は次のようになります。

actors
----actor
--------property

この場合、結果をどのように表示しますか?

actors
----actor
--------property
--------differentProperty
--------differentProperty2

また

actors
----actor
--------property
----actor
--------differentProperty
--------differentProperty2

またはこのケースは表示されませんか?

アップデート:

あなたのコメントを考えると、解決策は次のようになります。

public static string GetOutline(int indentLevel, XElement element)
{
    return GetGroupOutline(indentLevel, new[] {element});
}

/// <summary>
/// Returns the outline of the elements that constitute a group.
/// </summary>
/// <param name="indentLevel">Indent level.</param>
/// <param name="elements">Elements of a group (all the element of the collection must have the same <c>Name</c>)</param>
/// <returns>Outline of the group.</returns>
private static string GetGroupOutline(int indentLevel, IEnumerable<XElement> elements)
{
    StringBuilder result = new StringBuilder();

    // Adds the group name in the outline
    result = result.AppendLine(new string('-', indentLevel * 6) + elements.First().Name);

    foreach (var childGroup in from element in elements  // Gets each element in the group "elements"
                               from childElement in element.Elements()  // Gets their children
                               group childElement by childElement.Name into childGroup  // Groups the children of all elements by their name to a new group called "childGroup"
                               select childGroup)
        result.Append(GetGroupOutline(indentLevel + 1, childGroup));  // Shows the outline of the group called "groupChild"

    return result.ToString();
}
于 2013-01-20T11:36:01.083 に答える
0

最初に、すべての一意の要素を使用してxmlツリーを構築する必要があります。

private XElement GetUniqueElementsOf(XDocument xdoc)
{
    XElement result = new XElement(xdoc.Root.Name);
    AddUniqueChildren(result, xdoc.Root);
    return result;
}

public void AddUniqueChildren(XElement dest, XElement source)
{
    foreach (XElement sourceChild in source.Elements())
    {
        var destChild = dest.Elements()
                            .SingleOrDefault(x => x.Name == sourceChild.Name);

        if (destChild == null)
        {
            destChild = new XElement(sourceChild.Name);
            dest.Add(destChild);
        }

        AddUniqueChilds(destChild, sourceChild);
    }
}

2番目の方法では、xmlを再帰的にトラバースすることにより、すべての一意の子要素を各ノードに追加します。この時点で行う必要があるのは、出力結果だけです。

 var result = GetOutline(0, GetUniqueElementsOf(XDocument.Load(path_to_xml)));

アウトラインメソッドは、グループ化せずに単純にする必要があります(xmlの一意の要素のみが既に存在するため)。

public string GetOutline(int indentLevel, XElement element)
{
    StringBuilder result = new StringBuilder();

    result = result.AppendLine(new string('-', indentLevel * 2) + element.Name);

    foreach (var childElement in element.Elements())            
        result.Append(GetOutline(indentLevel + 3, childElement));            

    return result.ToString();
}
于 2013-01-20T12:25:07.063 に答える
0
internal static class ExtensionMethods
{
    public static List<XElement> Find(this XElement _objXElement, string _strFindXName)
    {
        List<XElement> _lsXElementsFound = new List<XElement>();
        try
        {
            List<XElement> _lsXElementsBundle = new List<XElement>();
            RecursiveSearch(_objXElement, _strFindXName, ref _lsXElementsBundle);
            if (_lsXElementsBundle != null && _lsXElementsBundle.Count > 0)
            {
                foreach (XElement _objCurrentXElement in _lsXElementsBundle)
                {
                    if (_objCurrentXElement != null)
                    {
                        if (!string.IsNullOrEmpty(_objCurrentXElement.Value))
                        {
                            _lsXElementsFound.Add(_objCurrentXElement);
                        }
                        else
                        {
                            _objCurrentXElement.Value = string.Empty;
                            _lsXElementsFound.Add(_objCurrentXElement);
                        }
                    }
                }
            }
        }
        catch (Exception _objException)
        {
            _lsXElementsFound = new List<XElement>();
            string _strDescription = NLOG.Utility.FormatEvent(MethodBase.GetCurrentMethod()
                , _objException.Message);
            NLOG.Log.Error(_strDescription);
        }
        return _lsXElementsFound;
    }

    #region "SUPPORT"

    private static void RecursiveSearch(XElement _objXElement, string _strFindXName
        , ref List<XElement> _lsOfXElementsFound)
    {
        try
        {
            if (_objXElement != null && !string.IsNullOrEmpty(_strFindXName)
                && _lsOfXElementsFound != null)
            {
                if (_objXElement.Name == _strFindXName)
                {
                    _lsOfXElementsFound.Add(_objXElement);
                }
                else
                {
                    foreach (XElement _objCurrentXElement in _objXElement.Elements())
                    {
                        RecursiveSearch(_objCurrentXElement, _strFindXName, ref _lsOfXElementsFound);
                    }
                }
            }
        }
        catch (Exception _objException)
        {
            string _strDescription = NLOG.Utility.FormatEvent(MethodBase.GetCurrentMethod()
                , _objException.Message);
            NLOG.Log.Error(_strDescription);
        }
    }

    #endregion
}
于 2014-11-18T21:49:29.633 に答える