Xelement.Descendants ("Nó") não se comportando como o esperado, retorna vários níveis de descendentes
Pergunta
Eu tenho um problema. Eu tenho dados XML hierárquicos como:
<Tree>
<Node Text="Stuff" ItemGUID="064a9bf0-0594-47f8-87be-88dd73763c77" >
<Node Text="Food" ItemGUID="326f1f7a-d364-4838-9bdc-ce5fd93f88ca" ItemType="2" />
<Node Text="Wines" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
<Node Text="Flowers" ItemGUID="cefa8c34-af06-48e7-9c00-4b1422d217a4">
<Node Text="Roses" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f">
<Node Text="Red" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
<Node Text="Pink" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
<Node Text="White" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
</Node>
<Node Text="Tulips" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
<Node Text="Whatever" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
</Node>
<Node Text="Sweet Delights" ItemGUID="1df7dbae-adf0-49a9-aaac-1358468a245b" />
</Node>
</Tree>
E eu preciso obter apenas flores (rosas, tulipas, o que for) sem vermelho, rosa, branco (sob rosas), estou usando o seguinte código, mas devido ao fato de que todos os nós são "nó", recebo todos os níveis de descendats . Eu gostaria de limitá -lo a apenas um nível.
XElement loadedXML = clients.ItemTreeXML;
//filter only current node
XElement procXML;
procXML = new XElement ("Tree",
from el in loadedXML.Descendants("Node")
where (string)el.Attribute("ItemGUID") == currentNodeGUID
select el);
Resultado procurado:
<Tree>
<Node Text="Flowers" ItemGUID="cefa8c34-af06-48e7-9c00-4b1422d217a4">
<Node Text="Roses" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
<Node Text="Tulips" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
<Node Text="Whatever" ItemGUID="950e3ca3-27a1-41fd-89f3-7a8b08633a9f" />
</Node>
</Tree>
Obrigado,
Adicionado: talvez uma consulta SQL 2008 possa recuperar apenas o ramo do nó de que preciso, mas depois de muitas pesquisas e testes, não consegui encontrar uma resposta ... (meu XML está em uma coluna XML em SQL 2008)
Solução
Então nós temos isso ...
XElement loadedXML = XElement.Load("test.xml");
//filter only current node
XElement procXML;
procXML = new XElement("Tree",
from el in loadedXML.Descendants("Node")
where (string)el.Attribute("ItemGUID") == currentNodeGUID
select el);
A melhor maneira que encontrei foi remover todos os elementos filhos depois de fazer a consulta do LINQ. Assim:
foreach (XElement xl in procXML.Element("Node").Elements("Node"))
{
if (xl.HasElements) // just remove the ones without child elements
{
xl.RemoveNodes();
}
}
Isso produzirá o que você desejou, mas devo acrescentar ... existe mais definitivamente Uma maneira melhor de fazer isso. Não sei o quão bem funcionará com sua situação, dada a maioria das necessidades de código escrito para funcionar mais dinamicamente do que isso.
Eu vi essa pergunta e decidi mergulhar no Linq, acho que não foi tão ruim assim. Se isso não funcionar da maneira que precisa, pelo menos é um começo.