2016-04-28 32 views
3

SOからの助けを借りて、次のLINQ式をまとめることができました。"PreviousNode"を使用したC#LINQ xmlの解析

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(); 

何それがないこと、それはmrkタグの位置を特定することである(つまり、@mtype="seg"を持っている)と、前の兄弟trans-unitが子供transがあり、場合ならば、それはtrans-unit祖先(.parent.parent)とチェックに上がりますそうでない場合は、nullを返します(nullを返す必要があります。一致を返すことはできません)。source子から最後のx要素の@idを返します。

以下のサンプルには、trans要素のないそのような前のノードが1つしかありませんが、現実のxmlにはもっと多くのものがありますので、PreviousNodeを使用する必要があります。ここで

はそれがで動作するXMLであり、完全に "2"を返します。

<?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> 

問題は、私は最後のステップは、カプセル化見つめtrans-unitを持っているXMLの別のタイプが存在することがあるとして解決する必要があるということです他のXMLには存在しない別のgroup要素内に存在します。だからここには上向きにジャンプし、groupの直前に、前のtrans-unitの兄弟を取得する親がもう1人あります。

これを同じLINQ式に組み込んで、両方のシナリオを処理しようとしています。実際に

私はこれに6行目を変更した場合、それは動作します:ここで

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

は今、上記のコードで例外がスローされますが、それは"0"を返す必要があり、他のXMLです:

<?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> 

私はどんな助けでも感謝以上のものになります。

+0

このお試しください:(itemb.Elements(のxmlns + &&).Where(itema =>(itema = NULLを! "x")!= null)) – jdweng

+0

@jdweng - あなたが 'itema'を意味すると思うのですが、' itemb'ではなく、これはスコープ内に存在しません。これにより例外が防止されますが、 "0"が返されません。 – ib11

答えて

2

は、代わりにXMLの構造に応じてParent数回使用してXMLツリーをナビゲートする、あなたはどちらか"trans-unit"または"group"という名前の最上位レベルの祖先を見つけるために、Ancestors().Last()を使用して試すことができ、その後、前のノードに移動します。

この部品を交換してください:この1と

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

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

OK、ありがとう。私はこれを試しました( 'new {] {" trans-unit "、" group "}'と 'new [] {" group "、" trans-unit "}' item!= null) 'itemの値は' 'です。これは' group'の下にあるので、最初の 'trans-unit'はマッチとみなされ、' PreviousNode'は'group'に行き、その' PreviousNode'にマッチしてください。 – ib11

+1

@ ib11私はそれが一度に存在する 'trans-unit'か' group'のどちらかと思っていました。 'は実際に' trans-unit'の親です。この場合、 'First()'の代わりに 'Last()'を使ってみてください – har07

+0

これは完全に動作します。どうもありがとう! – ib11