【问题标题】:linq query Map repeating EDI data to XML structurelinq 查询将重复 EDI 数据映射到 XML 结构
【发布时间】:2012-09-21 18:44:27
【问题描述】:

长话短说(详情见下文),有谁知道我可以构建一个查询以将重复数据返回为已知的 xml 格式,因此每个节点和子元素都会针对给定条件分别返回?
编辑: 我想我的问题归结为:如何查询重复数据,并获取一组条目,直到下一次出现重复?
UNB
联合国大学


联合国系统
UNT
联合国大学


联合国系统
UNT
联合国大学


联合国系统
UNT
联合国大学


联合国系统
UNT
联合国大学


联合国系统
UNT
因此,在这种情况下,知道某些段重复,我如何编写一个返回 UNH - UNT 的查询,分组为:
联合国大学


联合国系统
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+ORDERR319952+ORDERR:1::OD'
MID+ORDERR319952+120818'
DAN+:ADVICE NOTE+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+:ADVICE NOTE+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+:ADVICE NOTE+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'

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

【问题讨论】:

  • 有没有办法让你把它简化为本质?这两个 XML 清单和清单UNH+... 说明了什么?输出AddContentRecursive(本质上)是什么样的?应该是什么样的?
  • 右边xml的图像是我想要得到的。在解析EDI纯文本顺序文件时,我的翻译说每当我遇到UNH时创建一个MessageHeader xml节点,然后将MID段映射到DocumentNumber标签等等。所以从上面的示例中,我应该有两个 MessageHeader 节点,每个节点都有一个相应的 DocumentNumber 节点,一个父 DocumentReference 节点有几个子节点等等。我得到的是,所有父节点只出现一次,而它们的所有子节点都像左边的图像一样乱七八糟。
  • 我想从一个查询开始,该查询将返回组中的所有段类型,所以如果每个有 6 个,则 6 个组,每组 1 个 UNH、1 个 MID、1 个 DAN 等等,而不是我现在得到的是,它返回 6 UNH、6 DAN 等等。

标签: c# linq edi


【解决方案1】:

在独自绕圈跑了几个小时后,与同事进行了 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);

【讨论】:

  • 请帮自己一个忙,从 Liaison 下载 EDI 记事本。它是免费的(需要注册),并将帮助您了解 EDIFACT 的循环结构。 liaison.com/products/integrate/edi-notepad
  • 不幸的是,所有客户都创建和使用他们自己的 EDI 标准变体。所以每个新客户都需要一个新的映射(目前在 Delphi 中硬编码),我现在编写了一个概念证明通用映射器,它将 EDIFACT 转换为 XML 用于 ERP 输入。在这种情况下,记事本将无济于事。
猜你喜欢
  • 1970-01-01
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
  • 2013-06-13
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2021-08-13
相关资源
最近更新 更多