linq query将重复EDI数据映射到XML结构

时间:2012-09-30 19:41:34

标签: c# linq edi

长篇故事(详见下文)简介,是否有人知道我可以构建查询以将重复数据返回到已知的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

完整详情 我需要将一个通用edi(EDIFACT)写入xml映射器。由于xml是结构化的,并且我已经设计了应用程序来导入xml文件,因此使用实体框架提取并存储文件的结构。
enter image description here Xml结构存储为名为Translation的自引用实体。转换包含xml节点,它映射到的Edifact段名称以及从中提取值的复合和元素的位置。翻译还将自身引用为父/子关联(以镜像xml结构)。 UI自动将每个节点中的内容与段,复合和元素位置匹配。 我遇到的问题是如何将重复数据分成适当的重复父节点: 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的翻译实体有一个名为tag(MessageHeader)的属性和一个名为Name(UNH)的属性:

  

UNH + ORDERR319952 + ORDERR:1 :: OD'ENG MID + ORDERR319952 + 120818'
  DAN +:建议注意+ TGBGU649'
MSD + CR'
SDT + 0831824'
  BDT + PIPUK +++++ RB'
ART ++ 46210JD000 ::::: PIPE WORK,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 ::::: PIPE WORK,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'ENG MID + ORDERR340247 + 120818'
  DAN +:建议注意+ RRHBU641'
MSD + CR'
SDT + 0831824'
  BDT + PIPUK +++++ RB'
ART ++ 46210JD600 ::::: PIPE WORK,RH'
  DLV ++ 4200:45'
DTP + 120823:1700'
PIN + 21'
  TCO +:BAC4325 + 28 + 150'
CSG + 0831824 + F01-XJ10'
UNS + S'

  UNT + 14 + ORDERR340247'

我尝试了不同的查询,递归,循环组合,我知道我缺少一些基本的东西,我在砖墙领域。有人遇到过这种问题吗?任何有关塑造查询的建议,将不胜感激。 感谢

1 个答案:

答案 0 :(得分: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);
相关问题