循环以迭代父节点,直到找到特定标记

问题描述 投票:1回答:2

我正在做的是在XML文档中找到一个特定的值,然后我想向上遍历每个父项,直到找到具有特定标记名称的父项。

List<XElement> fieldReferences = new List<XElement>();
fieldReferences.AddRange(element.XPathSelectElements(string.Format("descendant::nameValue[@idref='{0}']", fieldName)));
fieldReferences.AddRange(element.XPathSelectElements(string.Format("descendant::nameValue[@value='{0}']", fieldName)));

string parentIterator = ".Parent";
string attributeValue = ".Attribute('id').Value";
string parentElementName = ".Name";
foreach (var value in fieldReferences)
{
    var parentField = string.Format("{0}{1}", parentIterator, parentElementName);
    while (value + parentField != "private" || value + parentField != "public")
        {
            // keep appending .Parent until it finds what it needs
        }
    //var parentField = value.Parent.Parent.Parent.Parent.Attribute("id").Value;
    outputFields.Add(parentField, name.FirstOrDefault());
}

我遇到的问题是,parentField将始终被评估为字符串,因此它永远不会实际检查value的.Parent.Name属性。

我不经常使用C#,所以我确定有一个更简单的方法来做到这一点,所以我的问题是:如何让我的parentField字符串来评估我想要的方式或者我怎么能以不同的方式做到这一点达到同样的最终结果?

编辑:这是我的xml的样子。 XPAthSelectElement获取nameValue元素,我想迭代每个父元素,直到找到私有标记

<private id="I need to iterate upwards through each parent element until I find this one">
    <value>
      <request>
        <nameValues>
          <nameValue idref="I found this" />
          <nameValue value=""/>
        </nameValues>
      </request>
    </value>
  </private>
c# loops xelement
2个回答
1
投票

所以你实际上不需要做很多字符串操作然后用XPath疯狂。一旦找到了您的子目标元素,您就可以迭代地使用Parent上的XElement属性,直到找到带有私有/公共标记的XElement。这样就给了我们这段代码:

foreach (XElement element in fieldReferences)
{
    XElement currentElement = element;
    while (currentElement.Parent != null)
    {
        currentElement = currentElement.Parent;
        if (currentElement.Name == "private" || currentElement.Name == "public") {
            outputFields.Add(currentElement, /* not sure what you want here */);
            break;
        }
    }
}

所以currentElement将从你的例子开始作为nameValue标签的元素。在while循环中,每次迭代currentElement都会更改为其父节点,直到没有更多父节点或currentElement变为privatepublic标记。如果是后者,则会将其附加到您的结果中。


1
投票

您可以使用XElement.Ancestors函数获取包含您找到的节点的所有元素的列表,然后只需使用LINQ选择您想要的节点。不需要任何循环。

var results = fieldReferences.Select(element => element.Ancestors()
                                                       .Where(ancestor => ancestor.Name == "public" ||
                                                                          ancestor.Name == "private")
                                                       .FirstOrDefault());

请注意,这将在树中一直向上,如果存在多个匹配的祖先(或没有匹配的祖先),则可能会出现问题。如果这对您来说是个问题,请告诉我,在这种情况下您想要的结果是什么,我可以进行调整。

© www.soinside.com 2019 - 2024. All rights reserved.