ciao, prego!
LittleAnt ha scritto:
Non esiste un modo per evitare proprio di ciclare?
Gli elementi vanno necessariamente esaminati uno ad uno. Anche quando non usi esplicitamente un foreach, ti devi affidare ad una query LINQ che internamente passa comunque in rassegna ogni elemento. Il vantaggio di usare una query LINQ è che resta più concisa e un po' più leggibile nel caso di logiche di filtraggio, ordinamento e proiezione complesse.
LittleAnt ha scritto:
In effetti devo generare un nuovo file xml
Ho modificato il mio precedente esempio in modo da fargli produrre il documento come serve a te. Ecco il link:
https://dotnetfiddle.net/IzhUC1In questo caso non ho usato il foreach ma una
select, che mi consente di emettere degli XElement.
LittleAnt ha scritto:
ma ho capito del tutto il funzionamento
La query seleziona solo gli elementi
o il cui id è 4 o 8
from o in root.Descendants("o")
where idAmmessi.Contains(o.Attribute("id").Value)
Da questa query otterresti una lista piatta di o, ma non è quello che vogliamo perché la gerarchia degli elementi e, b, o va preservata. Quindi raggruppo gli
o per il loro parent, in modo da ottenere la lista di
b in cui sono contenuti. In questo modo tengo fuori automaticamente gli
b che non avevano al loro interno degli
o rispondenti ai criteri di filtro.
group o by o.Parent into gruppo1
Fin qui ho ottenuto una lista piatta di
b, ma abbiamo bisogno di raggrupparli ulteriormente per il loro parent,
e.
group gruppo1 by gruppo1.Key.Parent into gruppo2
Infine proietto questi gruppi in nuovi XElement
select new XElement("e",
gruppo2.Key.Attributes(),
from b in gruppo2
select new XElement("b", b.Key.Attributes(), b)
));
LittleAnt ha scritto:
non ho ben capito se è più o meno efficiente
Non so stimare il tempo di esecuzione di questo algoritmo ma se sei alla ricerca del massimo delle prestazioni dovresti usare un XmlReader e un XmlWriter per leggere il documento in maniera forward-only e trascrivere i soli elementi che rispondono al tuo criterio. In questo modo, il documento non deve essere completamente caricato in memoria ed è una soluzione che scala bene anche con file grandi.
http://blogs.msdn.com/b/mfussell/archive/2005/02/12/371546.aspxSe decidi di continuare ad usare LINQ, un'altra possibile soluzione è quella di selezionare gli elementi che NON rispondono al criterio ed eliminarli dal documento originale. Ovviamente andrai a risalvarlo su un percorso diverso.
Ecco l'esempio:
https://dotnetfiddle.net/Tj8MCgIn questo caso seleziono tutti gli
o che NON possiedono un id uguale a 4 o 8 e li elimino. Poi elimino anche gli
b e gli
e che sono rimaasti senza discendenti. Questo approccio dovrebbe essere leggermente migliore dell'altro, perché di fatto stiamo modificando un unico documento, anziché crearne in memoria uno nuovo.
ciao,
Moreno
Modificato da BrightSoul il 07 marzo 2015 10.29 -