C# linq查询映射将EDI数据重复到XML结构

C# linq查询映射将EDI数据重复到XML结构,c#,linq,edi,C#,Linq,Edi,长话短说,大家知道我可以构建一个查询框架,将重复数据返回到一个已知的xml格式,这样每个节点和子元素都会根据给定的条件分别返回吗? 编辑:我想我的问题归结为:如何查询重复数据,并获得一组条目,直到下一次出现重复? UNB 嗯 中间 丹 UNS UNT 嗯 中间 丹 UNS UNT 嗯 中间 丹 UNS UNT 嗯 中间 丹 UNS UNT 嗯 中间 丹 UNS UNT 因此,在这种情况下,如果知道某些段会重复,我如何编写一个返回UNH-UNT的查询,分组如下: 嗯 中间 丹 UNS UNT 全部

长话短说,大家知道我可以构建一个查询框架,将重复数据返回到一个已知的xml格式,这样每个节点和子元素都会根据给定的条件分别返回吗? 编辑:我想我的问题归结为:如何查询重复数据,并获得一组条目,直到下一次出现重复? UNB 嗯 中间 丹 UNS UNT 嗯 中间 丹 UNS UNT 嗯 中间 丹 UNS UNT 嗯 中间 丹 UNS UNT 嗯 中间 丹 UNS UNT 因此,在这种情况下,如果知道某些段会重复,我如何编写一个返回UNH-UNT的查询,分组如下: 嗯 中间 丹 UNS UNT

全部细节 我需要编写一个通用的edi EDIFACT到xml映射器。由于xml是结构化的,我已经设计了应用程序来导入xml文件,使用实体框架提取和存储文件的结构。 Xml结构存储为一个称为Translation的自引用实体。转换包含xml节点、它映射到的Edifact段名称以及要从中提取值的组合和元素的位置。翻译还将自身引用为父/子关联,以镜像xml结构。UI会自动将每个节点中的内容与段、组合和元素位置相匹配。 我遇到的问题是如何将重复数据分离到相应的重复父节点中: 我通过在没有父对象的情况下提取翻译,然后递归地走下树来构建这一点:

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+Order319952+Order:1::OD“MID+Order319952+120818” DAN+:通知单+TGBGU649'MSD+CR'SDT+0831824' BDT+PIPUK+RB'ART++46210JD000: DLV++2160:45'DTP+120823:1700'引脚+21' TCO+:BLB+24+90'CSG+0831824+F01-XJ10'UNS+S' UNT+14+Order319952'UNH+Order340246+ORDERR:1::OD' MID+订单340246+120818'DAN+:通知单+RRHBU636' MSD+CR'SDT+0831824'BDT+PIPUK+RB' ART++46210JD005::管道工程,左侧“DLV++2160:45” DTP+120823:1700'引脚+21'TCO+:BLB+24+90' CSG+0831824+F01-XJ10'UNS+S'UNT+14+订单340246' UNH+Order340247+Order:1::OD“MID+Order340247+120818” DAN+:建议注释+RRHBU641'MSD+CR'SDT+0831824' BDT+PIPUK+RB'ART++46210JD600: DLV++4200:45'DTP+120823:1700'引脚+21' TCO+:BAC4325+28+150'CSG+0831824+F01-XJ10'UNS+S' UNT+14+订单340247'

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

在几个小时的单独兜圈子后,与同事进行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);

你有没有办法把它简化到本质上?这两个XML清单和清单UNH+是什么。。。证明输出AddContentRecursive本质上是什么样子的?它应该是什么样子的?右边的xml图像就是我想要得到的。在解析EDI纯文本序列文件时,我的翻译是每当遇到UNH时创建MessageHeader xml节点,然后中间段映射到DocumentNumber标记,依此类推。因此,从上面的示例中,我应该有两个MessageHeader节点,每个节点都有一个对应的DocumentNumber节点,一个父DocumentReference节点有几个子节点,依此类推。我得到的结果是,所有的父节点只出现一次,而它们的所有子节点混乱在一起,如左图所示。我假设从一个查询开始,该查询将返回组中的所有段类型,因此,如果每个组中有6个,6个组,1个UNH,1个MID,1个DAN等等,而不是我现在得到的,它将返回6个UNH,请帮自己一个忙,从联络处下载EDI记事本。它免费注册,并将帮助您了解EDIFACT的循环结构。不幸的是,所有客户都创建并使用自己的EDI标准变体。因此,每个新客户都需要一个新的映射(目前已在Delphi中硬编码),我现在编写了一个概念验证通用映射器,它将EDIFACT转换为XML以用于ERP输入。在这种情况下,记事本没用。