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

完整详细信息 我需要将通用 edi (EDIFACT) 写入 xml 映射器。由于 xml 是结构化的,并且已知我已经设计应用程序来导入 xml 文件,使用实体框架提取和存储文件的结构。
在此处输入图像描述 Xml 结构存储为称为 Translation 的自引用实体。翻译包含 xml 节点、它映射到的 Edifact 段名称以及要从中提取值的组合和元素的位置。翻译也将自身引用为父/子关联(以反映 xml 结构)。UI 会自动将每个节点中的内容与段、复合和元素位置进行匹配。我遇到的问题是如何将重复数据分离到适当的重复父节点中: 所需的 XML 结构在右侧,我的输出在左侧 我通过在没有父母的情况下提取翻译来构建它,然后递归地沿着树走:

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'

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

4

1 回答 1

0

After hours of solitary running in circles, a 10 minute discussion with a colleague yields a working solution. It was to let the segments determine the flow (instead of the mapping like I intended).

EDI data is sequential, and by extension the segments are also sequential, therefore it was a matter of stepping through each segment, paired with its translation or map, and using place holders to create and nest the XML nodes.

Not the prettiest (there are likely better ways of doing the same thing), but it works consistently:

// 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);
于 2012-10-01T11:29:15.130 回答