2016-04-28 2 views
3

Mit einiger Hilfe von SO, habe ich den folgenden LINQ-Ausdruck zusammengestellt.C# LINQ XML-Parsing mit "PreviousNode"

var parentids = xliff.Descendants() 
        .Elements(xmlns + "trans-unit") 
        .Elements(xmlns + "seg-source") 
        .Elements(xmlns + "mrk") 
        .Where(e => e.Attribute("mtype").Value == "seg") 
        .Select(item => (XElement)item.Parent.Parent.PreviousNode) 
         .Where(item => item != null) 
         .Select(item => item.Elements(xmlns + "source") 
          .Where(itema => itema != null) 
          .Select(itemb => itemb.Elements(xmlns + "x")    
          .LastOrDefault() 
          .Attribute("id") 
          .Value.ToString())).ToArray(); 

Was sie tut, ist, dass es einen mrk Tag lokalisiert (das hat @mtype="seg") und es geht dann bis zum trans-unit Vorfahren (.parent.parent) und prüft, ob die vorherigen Geschwister trans-unit ein Kind haben trans und wenn nicht, es kommt aus dem source Kind der @id des letzten x Elements zurück, sonst gibt es null zurück (es muss null zurückgeben, kann nicht einfach nicht zurückpassen).

Ich muss hinzufügen, dass während die folgenden Beispiele nur einen solchen vorherigen Knoten ohne trans Element haben, in der realen xml gibt es viele mehr, also muss ich PreviousNode verwenden. Hier

ist die XML funktioniert es mit und gibt "2" perfekt:

<?xml version="1.0" encoding="utf-8"?> 
<xliff xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0" version="1.2" sdl:version="1.0" xmlns="urn:oasis:names:tc:xliff:document:1.2"> 
    <file original="Pasadena_Internet_2016.xml" source-language="en-US" datatype="x-sdlfilterframework2" target-language="da-DK"> 
    <body> 
     <trans-unit id="d679cb2d-ecba-47ba-acb7-1bb4a798c755" translate="no"> 
     <source> 
      <x id="0" /> 
      <x id="1" /> 
      <x id="2" /> 
     </source> 
     </trans-unit> 
     <trans-unit id="aed9fde2-fd1b-4eba-bfc9-06d325aa7047"> 
     <source> 
      <x id="3" />Pasadena, California’s iconic Colorado Boulevard <x id="4" />has been the site of the world-famous Tournament of Roses Parade since it began in 1890. 
     </source> 
     <seg-source> 
      <mrk mtype="seg" mid="1"> 
      <x id="3" />Pasadena, California’s iconic Colorado Boulevard <x id="4" />has been the site of the world-famous Tournament of Roses Parade since it began in 1890. 
      </mrk> 
     </seg-source> 
     <target> 
      <mrk mtype="seg" mid="1"> 
      <x id="3" /><x id="4" />Pasadena, Californiens ikoniske Colorado Boulevard har været stedet for den verdensberømte Rose Bowl-parade siden den begyndte i 1890. 
      </mrk> 
     </target> 
     </trans-unit> 
    </body> 
    </file> 
</xliff> 

Das Problem ist, dass ich zu lösen, wie ein letzter Schritt besteht darin, dass es eine andere Art von XML, die die starren trans-unit hat verkapselt innerhalb eines anderen group Elements, das in der anderen XML nicht vorhanden ist. Also hier gibt es einen weiteren Elternteil, um nach oben zu springen und den vorherigen trans-unit Geschwister direkt vor dem group zu bekommen.

Ich versuche, dies in den gleichen LINQ Ausdruck zu erstellen, so dass es beide Szenarien behandelt.

In der Tat, wenn ich die Linie 6 bis diese ändern, dann funktioniert es:

.Select(item => (XElement)item.Parent.Parent.Parent.PreviousNode) 
<!--          ^------ additional Parent --> 

Hier ist die andere XML ist das jetzt eine Ausnahme mit dem obigen Code wirft, aber es sollte "0" zurück:

<?xml version="1.0" encoding="utf-8"?> 
<xliff xmlns:sdl="http://sdl.com/FileTypes/SdlXliff/1.0" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2" sdl:version="1.0"> 
    <file original="Internet_Anti-DrugIntro2015.xml_1457007.xlf" datatype="x-sdlfilterframework2" source-language="en-US" target-language="hu-HU"> 
    <body> 
     <trans-unit translate="no" id="c3a13bfb-ed51-49cf-8278-e2c86c2114c0"> 
     <source> 
      <x id="0"/> 
     </source> 
     </trans-unit> 
     <group> 
     <sdl:cxts> 
      <sdl:cxt id="1"/> 
     </sdl:cxts> 
     <trans-unit id="3b4520df-4483-4c9e-8a9b-ce2544269f3e"> 
      <source> 
      <x id="1"/> 
      </source> 
      <seg-source> 
      <mrk mtype="seg" mid="2"> 
       <x id="1"/>Drugs are robbing our children of their future. 
      </mrk> 
      <mrk mtype="seg" mid="3"> 
       <x id="2"/>Every 17 seconds a teenager experiments with an illicit drug for the first time. 
      </mrk> 
      </seg-source> 
      <target> 
      <mrk mtype="seg" mid="2"> 
       <x id="1"/>A drogok megfosztják gyermekeinket a jövőjüktől. 
      </mrk> 
      <mrk mtype="seg" mid="3"> 
       <x id="2"/>17 másodpercenként egy újabb tizenéves próbálja ki először a kábítószereket. 
      </mrk> 
      </target> 
     </trans-unit> 
     </group> 
     <trans-unit translate="no" id="7890462c-edcb-4fe6-9192-033ba76d9942"> 
     <source> 
      <x id="183"/> 
     </source> 
     </trans-unit> 
    </body> 
    </file> 
</xliff> 

Ich werde für jede Hilfe mehr als dankbar sein.

+0

starten: .Where (itema => (itema = null) && (itemb.Elements (xmlns + "x")! = null)) – jdweng

+0

@jdweng - Ich denke, du meintest "itema" nicht "itemb", das existiert nicht im Umfang. Während dies die Ausnahme verhindert, gibt es nicht "0" zurück, wie es sollte. – ib11

Antwort

2

Statt die XML-Struktur mit Parent mehrmals von der Navigation auf der XML-Struktur abhängig, können Sie mit Ancestors().Last() versuchen, die höchsten Ebene Vorfahren finden genannt entweder "trans-unit" oder "group" und dann zum vorherigen Knoten navigieren.

Versuchen, diesen Teil zu ersetzen:

.Select(item => (XElement) item.Parent.Parent.PreviousNode) 

mit dieser:

.Select(item => (XElement)item.Ancestors() 
           .Last(o => new[]{"trans-unit","group"}.Contains(o.Name.LocalName)) 
           .PreviousNode) 
+0

OK, danke. Ich habe das versucht (sowohl 'new [] {" trans-unit "," group "}' und 'new [] {" group "," trans-unit "}' aber in der nächsten Zeile '.Where (item => item! = null) 'der Wert des Items ist' ', was unterhalb der' group' liegt, so scheint es, dass die erste 'trans-unit' als Übereinstimmung genommen wird und dann ihr' PreviousNode' statt dessen gefunden wird gehe zu "group" und passe dann den "PreviousNode" davon an. – ib11

+1

@ ib11 mein Schlechter, ich dachte, es wäre entweder 'trans-unit' oder' group', die zu einer Zeit existieren, habe diese 'Gruppe nicht bemerkt 'ist eigentlich Mutter von' trans-unit'.Versuchen Sie in diesem Fall 'Last()' anstelle von 'First()' – har07

+0

zu verwenden. Dies funktioniert einwandfrei. Danke vielmals! – ib11