如何连接两个 XML 表并嵌套而不重复

Posted

技术标签:

【中文标题】如何连接两个 XML 表并嵌套而不重复【英文标题】:How to join two XML tables and nest it without repeating 【发布时间】:2021-09-08 07:23:37 【问题描述】:

我正在尝试加入下面的两个 XML 文件

XML 文件 1 - 日志

<Journals>
    <JournalID>1</JournalID>
    <Description>BKI- 1</Description>
</Journals>
<Journals>
    <JournalID>2</JournalID>
    <Description>BKI- 2</Description>
</Journals>

XML 文件 2 - 事务

<Transaction>
    <JID>1</JID>
    <TransactionID>0005932053</TransactionID>
    <Period>5</Period>
</Transaction>
<Transaction>
    <JID>1</JID>
    <TransactionID>0005932054</TransactionID>
    <Period>8</Period>
</Transaction>
<Transaction>
    <JID>2</JID>
    <TransactionID>0005932053</TransactionID>
    <Period>2</Period>
</Transaction>
<Transaction>
    <JID>2</JID>
    <TransactionID>0005932053</TransactionID>
    <Period>4</Period>
</Transaction>

变成如下图

XML 输出

<Journals>
    <JournalID>1</JournalID>
    <Description>BKI- 1</Description>
        <Transaction>
            <JID>1</JID>
            <TransactionID>0005932053</TransactionID>
            <Period>5</Period>
        </Transaction>
        <Transaction>
            <JID>1</JID>
            <TransactionID>0005932054</TransactionID>
            <Period>8</Period>
        </Transaction>
</Journals>
<Journals>
    <JournalID>2</JournalID>
    <Description>BKI- 2</Description>
        <Transaction>
            <JID>2</JID>
            <TransactionID>0005932053</TransactionID>
            <Period>2</Period>
        </Transaction>
        <Transaction>
            <JID>2</JID>
            <TransactionID>0005932053</TransactionID>
            <Period>4</Period>
        </Transaction>

</Journals>

如您所见,我正在尝试加入它,以便对于每个日记 - 所有交易都将显示为子节点。

到目前为止我的代码 - 未能做到这一点(因为它为每个事务复制 Journals 节点):

        XDocument FileTransactions = XDocument.Load("Final_Transaction.xml");
        XDocument FileJournals = XDocument.Load("Final_Journals.xml");
        var joinQuery = from j in FileJournals.Root.Descendants("Final_Journals")

                        join t in FileTransactions.Root.Descendants("Final_Transaction")

                        on (string)j.Element("JournalID").Value equals (string)t.Element("JID").Value

                        select new XElement("Journals",
        new XElement("JournalID", (string)j.Element("JournalID")),
        new XElement("Description", (string)j.Element("Description")),
        new XElement("Type", (string)j.Element("Type")),
        new XElement("Transaction", new XElement(t))
                );

我需要在这里添加一个 foreach 循环吗?如何在不重复父节点的情况下搭建父节点中的所有相关子节点?

我已经尝试查看教程和其他帖子 - 它们都没有涵盖我面临的复杂性

请指出正确的方向

【问题讨论】:

我会遍历事务文件并将所有单个事务保存到字典中,其中键是JID,值是事务列表。然后我会遍历日志文件并使用Add 方法注入相应的事务(通过JournalID)。 【参考方案1】:

您可以使用 for 循环或 join(使用 for 循环)。我用加入。您需要使用格式良好的 xml,因此我在输入中添加了根标签。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;

namespace ConsoleApplication1

    class Program
    
        const string journalsStr = @"c:\temp\test.xml";
        const string transactionsStr = @"c:\temp\test1.xml";
        static void Main(string[] args)
        
            // xml files are not well formed. A well formed xml has only one root tag
            string jXml = File.ReadAllText(journalsStr);
            jXml = string.Format("<Root>0</Root>", jXml);
            XDocument jDoc = XDocument.Parse(jXml);
            string tXml = File.ReadAllText(transactionsStr);
            tXml = string.Format("<Root>0</Root>", tXml);
            XDocument tDoc = XDocument.Parse(tXml);

            var query = (from j in jDoc.Descendants("Journals")
                          join t in tDoc.Descendants("Transaction") on (int)j.Element("JournalID") equals (int)t.Element("JID")
                         select new j = j, t = t
                         ).ToList();

            var groups = query.GroupBy(x => (int)x.j.Element("JournalID")).ToList();

            string root = "<Journals></Journals>";
            XDocument doc = XDocument.Parse(root);
            XElement journals = doc.Root;
            foreach (var group in groups)
            
                XElement journal = group.First().j;
                foreach (var trans in group)
                
                    journal.Add(trans.t);
                
                journals.Add(journal);
            
        
    

【讨论】:

jdweng,非常感谢你——这正是我所需要的。我有点惊讶没有在线教程来解决这类问题......但是你用你的解决方案让我很开心。你是明星!

以上是关于如何连接两个 XML 表并嵌套而不重复的主要内容,如果未能解决你的问题,请参考以下文章

如何在同一个li元素中处理2个嵌套循环而不重复

从mysql连接两个表并在一个JSP列表中显示信息[重复]

MySQL连接和连接行而不重复条目[重复]

9嵌套Fors而不重复过去的数字

使用 SASS 连接嵌套类 [重复]

连接 2 个表并根据其关联 ID 重复显示同一列