Aanpassingen van XML-bomen in het geheugen versus functionele opbouw (LINQ naar XML)

Het ter plaatse wijzigen van een XML-boom is een traditionele benadering om de vorm van een XML-document te veranderen. Een typische toepassing laadt een document in een gegevensarchief zoals DOM of LINQ naar XML; maakt gebruik van een programmeerinterface om knooppunten in te voegen of te verwijderen of hun inhoud te wijzigen; en slaat de XML vervolgens op in een bestand of verzendt het via een netwerk.

LINQ naar XML maakt een andere benadering mogelijk die nuttig is in veel scenario's: functionele constructie. Functionele constructie behandelt het wijzigen van gegevens als een probleem van transformatie, in plaats van als gedetailleerde manipulatie van een gegevensarchief. Als u een weergave van gegevens kunt maken en deze efficiënt van het ene formulier naar het andere kunt transformeren, is het resultaat hetzelfde als als als u één gegevensarchief hebt genomen en op een bepaalde manier hebt bewerkt om een andere vorm te nemen. Een sleutel tot de functionele bouwbenadering is het doorgeven van de resultaten van query's aan XDocument en XElement constructors.

In veel gevallen kunt u de transformatiecode schrijven in een fractie van de tijd die nodig is om het gegevensarchief te manipuleren en de resulterende code is robuuster en eenvoudiger te onderhouden. In dergelijke gevallen is het een effectievere manier om gegevens te wijzigen, ook al kan de transformatie meer verwerkingskracht gebruiken. Als een ontwikkelaar bekend is met de functionele benadering, is de resulterende code in veel gevallen gemakkelijker te begrijpen en is het gemakkelijk om de code te vinden die elk deel van de structuur wijzigt.

De benadering waarin u een XML-structuur wijzigt, is bekender voor veel DOM-programmeurs, terwijl code die is geschreven met behulp van de functionele benadering misschien onbekend is voor een ontwikkelaar die die benadering nog niet begrijpt. Als u slechts een kleine wijziging moet aanbrengen in een grote XML-boom, kost het in veel gevallen minder CPU-tijd om de boom ter plekke te wijzigen.

Dit artikel bevat voorbeelden van beide benaderingen. Stel dat u het volgende eenvoudige XML-document wilt wijzigen, zodat de kenmerken elementen worden:

<?xml version="1.0" encoding="utf-8" ?>
<Root Data1="123" Data2="456">
  <Child1>Content</Child1>
</Root>

De eerste van de volgende voorbeelden maakt gebruik van de traditionele in-place aanpassingsbenadering en de tweede maakt gebruik van de functionele bouwmethode.

Voorbeeld: Kenmerken transformeren in elementen met de traditionele in-place benadering

U kunt enkele procedurele code schrijven om elementen van de kenmerken te maken en vervolgens de kenmerken als volgt te verwijderen:

XElement root = XElement.Load("Data.xml");
foreach (XAttribute att in root.Attributes()) {
    root.Add(new XElement(att.Name, (string)att));
}
root.Attributes().Remove();
Console.WriteLine(root);
Dim root As XElement = XElement.Load("Data.xml")
For Each att As XAttribute In root.Attributes()
    root.Add(New XElement(att.Name, att.Value))
Next
root.Attributes().Remove()
Console.WriteLine(root)

In dit voorbeeld wordt de volgende uitvoer gegenereerd:

<Root>
  <Child1>Content</Child1>
  <Data1>123</Data1>
  <Data2>456</Data2>
</Root>

Voorbeeld: Kenmerken transformeren in elementen met de functionele constructiebenadering

Een functionele benadering bestaat daarentegen uit code om een nieuwe structuur te vormen, elementen en kenmerken uit de bronstructuur te kiezen en deze zo nodig te transformeren als ze worden toegevoegd aan de nieuwe structuur.

XElement root = XElement.Load("Data.xml");
XElement newTree = new XElement("Root",
    root.Element("Child1"),
    from att in root.Attributes()
    select new XElement(att.Name, (string)att)
);
Console.WriteLine(newTree);
Dim root As XElement = XElement.Load("Data.xml")
Dim newTree As XElement = _
    <Root>
        <%= root.<Child1> %>
        <%= From att In root.Attributes() _
            Select New XElement(att.Name, att.Value) %>
    </Root>
Console.WriteLine(newTree)

In dit voorbeeld wordt dezelfde XML uitgevoerd als in het eerste voorbeeld. U ziet echter wel de resulterende structuur van de nieuwe XML in de functionele benadering. U ziet het maken van het Root element, de code die het Child1 element uit de bronstructuur haalt en de code waarmee de kenmerken van de bronstructuur worden getransformeerd naar elementen in de nieuwe structuur.

Het functionele voorbeeld in dit geval is niet korter of eenvoudiger dan het eerste voorbeeld. Als u echter veel wijzigingen aanbrengt in een XML-structuur, wordt de procedurele benadering behoorlijk complex en enigszins onzinnig. Wanneer u de functionele benadering gebruikt, kunt u daarentegen nog steeds gewoon de gewenste XML vormen, query's en expressies insluiten om de gewenste inhoud op te halen. De functionele benadering levert code op die gemakkelijker te onderhouden is.

U ziet dat in dit geval de functionele benadering waarschijnlijk niet zo goed zou presteren als de boommanipulatiebenadering. Het belangrijkste probleem is dat de functionele benadering meer kortlevende objecten creëert. Het compromis is echter een effectief compromis als het gebruik van de functionele benadering een grotere productiviteit van programmeurs mogelijk maakt.

Dit is een heel eenvoudig voorbeeld, maar het dient om het verschil in filosofie tussen de twee benaderingen weer te geven. De functionele benadering levert hogere productiviteitswinsten op voor het transformeren van grotere XML-documenten.