2012-09-30 74 views
1

長篇故事(詳見下文)簡短,有誰知道我可以構建一個查詢來將重複數據轉換爲已知的xml格式,因此每個節點和子元素分別返回一個給定的標準?
編輯:我想我的問題歸結爲:我如何查詢重複數據,並獲得一組條目,直到下一次出現重複?
UNB
UNH
MID
DAN
UNS
UNT
UNH
MID
DAN
UNS
UNT
UNH
MID
DAN
UNS
UNT
UNH
MID
DAN
UNS
UNT
UNH
MID
DAN
UNS
UNT
所以在這種情況下,明知某些環節重複,我怎麼能寫一個將返回UNH - UNT的查詢,分組爲:
UNH
MID
DAN
UNS
UNT
linq查詢將EDI數據重複映射到XML結構

全部詳細 我必須寫一個通用的EDI(電子數據交換)到XML映射器的要求。由於xml是結構化的,並且我已經設計了應用程序來導入xml文件,所以使用實體框架提取並存儲文件的結構。
enter image description here Xml結構存儲爲一個名爲Translation的自引用實體。該翻譯包含xml節點,它映射到的Edifact段名稱以及要從中提取值的組合和元素的位置。翻譯還將其自身引用爲父/子關聯(以反映xml結構)。用戶界面會自動將每個節點中的內容與該段以及複合和元素位置進行匹配。 我的問題是如何將重複數據分爲適當的重複父節點: Desired XML structure on right, my output on left 我建立這個由沒有父母提取的翻譯,然後遞歸走在樹:

var rootTrans = (from t in Translations 
        where t.ParentID==null 
        select t).ToList(); 
//(msg is the EDI transmission with a collection of segments-each segment contains composites, each composite contains elements with the actual data eg-) 

XElement root = new XElement(Tag.Replace(" ", "")); 
foreach (var item in rootTrans) 
{ 
    item.AddContentRecursive(root, msg); 
} 

var doc = new XDocument(root); 



// AddContentRecursive 
public void AddContentRecursive(XElement element, Transmission msg) 
{ 
    // Find matching segments for this tag 
    var segNodes = (from s in msg.Segments 
         where s.Value == Name 
         select GetElementValue(s, Positions)).DefaultIfEmpty(null); 
    // simply add the matching nodes to the parent element 
    if (Children.Count == 0) 
    { 
     var nodes = (from t in segNodes 
         select new XElement(Tag, t)); 
     element.Add(nodes); 
    } 
    else 
    { 
     var aNode = new XElement(Tag); 
     element.Add(aNode); 
     foreach (var chil in Children.OrderBy(c => c.DocumentOrder)) 
     { 
      chil.AddContentRecursive(aNode, msg); 
     } 
    } 
} 

的EDI文件被控制由客戶,並遵循自己的模式,從下面的例子UNH段是一個消息標題,並將重複,直到UNT。對於UNH翻譯實體有一個屬性叫做標籤(的MessageHeader)和一個名爲Name(UNH):

UNH + ORDERR319952 + ORDERR:1 :: OD」
MID + ORDERR319952 + 120818'
DAN +:建議注+ TGBGU649'
MSD + CR '
SDT + 0831824'
BDT + PIPUK +++++ RB'
ART ++ 46210JD000 :::::管道工程,RH」
DLV ++ 2160:45'
DTP + 120823:1700'
PIN + 21'
TCO +:BLB + 24 + 90'
CSG + 0831824 + F01-XJ10'
UNS + S '
UNT + 14 + ORDERR319952'
UNH + ORDERR340246 + ORDERR:1 :: OD'
MID + ORDERR340246 + 120818'
DAN +:通知書+ RRHBU636'
MSD + CR」
SDT + 0831824'
BDT + PIPUK +++++ RB '
ART ++ 46210JD005 :::::管道工程,LH'
DLV ++ 2160:45'
DTP + 120823:1700'
PIN + 21'
TCO +:BLB + 24 + 90'
CSG + 0831824 + F01-XJ10'
UNS + S'
UNT + 14 + ORDERR340246'
UNH + ORDERR340247 + ORDERR:1 :: OD '
MID + ORDERR340247 + 120818'
DAN +:通知書+ RRHBU641'
MSD + CR'
SDT + 0831824'
BDT + PIPUK +++++ RB」
ART ++ 46210JD600 :::::管道工程,RH」
DLV ++ 4200:45'
DTP + 120823:1700'
PIN + 21'
TCO +:BAC4325 + 28 + 150'
CSG + 0831824 + F01-XJ10'
UNS + S」
UNT + 14 + ORDERR340247'

我試過查詢,遞歸,循環的不同組合,我知道我錯過了一些基本的東西,我在磚牆領域。有沒有人遇到過這種問題?任何建議來塑造查詢,將不勝感激。 謝謝

+0

有沒有一種方法可以讓你削減下來的本質是什麼?這兩個XML列表和UNH + ...列表顯示了什麼?輸出「AddContentRecursive」(基本上)是什麼樣的,它應該是什麼樣的? –

+0

右邊的xml圖像是我想要得到的。在解析EDI純文本順序文件時,我的翻譯說每當我遇到UNH時創建一個MessageHeader xml節點,然後將MID段映射到DocumentNumber標記等等。所以從上面的示例中我應該有兩個MessageHeader節點,每個節點都有一個對應的DocumentNumber節點,一個具有多個子節點的父DocumentReference節點,等等。我得到的是,所有的父節點都只出現一次,像左邊的圖像一樣,他們所有的子節點都一團糟。 – reckface

+0

我想開始一個查詢,它將返回所有的分組類型,所以如果每個分組有6個,6個組1個UNH,1個MID,1個DAN等等,而不是我現在得到的,它返回6 UNH,6 DAN等等。 – reckface

回答

0

經過幾個小時的孤獨運行後,與同事進行了10分鐘的討論,得出了一個可行的解決方案。這是讓細分市場決定流量(而不是我想要的映射)。

EDI數據是連續的,並且通過擴展該段也是順序的,因此它是逐步遍歷每個段,與其翻譯或映射配對以及使用佔位符創建和嵌套XML節點的問題。

不是最漂亮的(也有可能做同樣的事情的更好的方式),但它的工作原理一致:

// Get a collection of segments and maps 
var SegsAndMaps = (from s in msg.Segments 
        join t in Maps on s.Value equals t.Name 
        orderby s.Id 
        select new { Segment = s, Map = t }).ToList(); 
// Set the placeholders 
currentNode = null; 
currentParent = null; 
for (int i = 0; i < SegsAndMaps.Count; i++) 
{ 
    var item = SegsAndMaps[i]; 
    // Separate the properties from anonymous type for clarity 
    var aMap = item.Map; 
    var aSegment = item.Segment; 
    var xml = aSegment.Xml(aMap); 
    // If this map shares the same parent 
    if (aMap.Parent == currentParent) 
    { 
     // Add the xml to the current node 
     currentNode.Add(xml); 
    } 
    else 
    { 
     // Change of parent, walk up the tree to get the right parent 
     var trans = aMap; 
     while (currentParent != aMap.Parent) 
     { 
      trans = trans.Parent; 
      currentParent = trans.Parent; 
     } 
     // Walk up the xml tree to find the parent tag to add this xml to 
     currentNode = currentNode.Ancestors().DescendantsAndSelf(currentParent.Tag).FirstOrDefault(); 
     currentNode.Add(xml); 
    } 
    if (aMap.Children.Count > 0) 
    { 
     // If this map has child mappings, then update current parent to this, and its xml as the current node 
     currentNode = xml; 
     currentParent = aMap; 
    } 
} 

var doc = new XDocument(currentNode); 
+0

請自己幫忙,並從Liaison下載EDI記事本。它是免費的(有註冊),並且可以幫助您瞭解EDIFACT的循環結構。 http://liaison.com/products/integrate/edi-notepad – Andrew

+0

不幸的是,所有的客戶都創建並使用他們自己的EDI標準變體。因此,每個新客戶都需要一個新的映射(目前在Delphi中進行了硬編碼),現在我寫了一個概念證明通用映射器,將EDIFACT轉換爲用於ERP輸入的XML。記事本在這種情況下不起作用。 – reckface