我正在做的是在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将始终被评估为字符串,因此它永远不会实际检查值的.Parent.Name属性。
我不经常使用C#工作,所以我确信这样做更容易,所以我的问题是:如何让我的parentField字符串来评估我想要的方式OR如何以不同的方式实现相同的最终结果呢?
编辑:这是我的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>
答案 0 :(得分: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
成为private
或public
标记。如果是后一种情况,则会将其附加到您的结果中。
答案 1 :(得分:1)
您可以使用XElement.Ancestors
函数获取包含您找到的节点的所有元素的列表,然后只需使用LINQ选择您想要的节点。不需要任何循环。
var results = fieldReferences.Select(element => element.Ancestors()
.Where(ancestor => ancestor.Name == "public" ||
ancestor.Name == "private")
.FirstOrDefault());
请注意,这将在树上一直向上,如果有多个匹配的祖先(或没有匹配的祖先),则可能会出现问题。如果这对您来说是个问题,请告诉我,在这种情况下您想要的结果是什么,我可以进行调整。