2016-04-28 58 views
3

在SO的幫助下,我設法將以下LINQ表達式放在一起。C#LINQ xml使用「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(); 

它所做的是,它找到了一個mrk標籤(即具有@mtype="seg"),然後將其上升到trans-unit祖先(.parent.parent)並檢查前一個兄弟trans-unit有一個孩子trans如果不是,它從source孩子返回最後x元素的@id,否則返回null(它必須返回null,不能只是不返回匹配)。

我需要補充的是,雖然下面的例子只有一個這樣的前一個節點沒有trans元素,在現實生活中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> 

的問題是,我需要解決的最後一步是,有另一種類型的XML具有封裝在盯着trans-unit在另一個XML中不存在的另一個group元素中。所以這裏還有一位家長向上跳,並獲得之前的trans-unit兄弟姐妹,就在group之前。

我想建立這個到相同的LINQ表達式,所以它處理這兩種情況。

事實上,如果我修改6號線這一點,那麼它的工作原理:

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

下面是其他XML是現在投用上面的代碼中的例外,但它應該返回"0"

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

試試:!。凡(意達=>(意達= NULL)&&(itemb.Elements(的xmlns + 「x」)!= null)) – jdweng

+0

@jdweng - 我想你的意思是'itema'而不是'itemb',這在範圍中不存在。雖然這可以防止發生異常,但它不會返回「0」。 – ib11

回答

2

而不是向上導航使用Parent幾次取決於XML結構的XML樹,你可以嘗試使用Ancestors().Last()去找一個或者"trans-unit""group"最高級別的祖先,然後導航到前一個節點。與這一個

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

嘗試更換這部分

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

好的,謝謝。我試過這個(new [] {「trans-unit」,「group」}'和'new [] {「group」,「trans-unit」}',但是在下一行'.Where(item => item!= null)'item的值是'',它低於'group',所以看起來第一個'trans-unit'被視爲匹配,然後它的'PreviousNode'被匹配,而不是去'group'然後再匹配'PreviousNode' – ib11

+1

@ ib11我的不好,我以爲它可能是'trans-unit'或'group',一次存在,沒有注意到'group '實際上是'trans-unit'的父項。在這種情況下,嘗試使用'Last()'而不是'First()' – har07

+0

這很好。非常感謝! – ib11