【问题标题】:Using C# to copy different nodes from two files and pasting it on a third one使用 C# 从两个文件中复制不同的节点并将其粘贴到第三个文件中
【发布时间】:2021-11-10 02:18:33
【问题描述】:

我有一项非常繁琐的任务,因为我必须手工完成(我的公司花了一大笔钱买了一个工具,但现在已经不工作了)。

我有两个 XML 列表,每个列表都缺少一半,所以我需要将它拼凑成第三个,然后再发送到系统。以及将标题更改为我发送文件的日期。

我已经成功地设置了日期的输入,向用户询问输入很容易。但是剩下的任务让我发疯,我尝试了很多我在这里和微软论坛上找到的东西,但无济于事......这个任务让我很生气,因为我是唯一一个“精通技术的人” " 来做(从 XML 中复制和粘贴文本简直是猴子的工作)。

显然不是卡车和汽车,而且文件多于两个,但它们都是这样的:一种只有汽车,有一个空的卡车节点,另一种有卡车但有一个空的汽车节点。

文件 1 示例

<?xml version="1.0" encoding="utf-8"?>
<document>
<header>
    <startDate>01/01/2020</startDate>
    <endDate>01/02/2020</endDate>
</header>
<body>
    <cars>
        <car>
            <ID>1</ID>
            <Name>Blue Car</Name>
        </car>
        <car>
            <ID>2</ID>
            <Name>Red Car</Name>
        </car>
    </cars>
    <trucks>
    </trucks>
</body>
</document>

文件 2 示例

<?xml version="1.0" encoding="utf-8"?>
<document>
<header>
    <startDate>01/01/2020</startDate>
    <endDate>01/02/2020</endDate>
</header>
<body>
    <cars>
    </cars>
    <trucks>
        <truck>
            <ID>1</ID>
            <Name>Blue Truck</Name>
        </truck>
        <truck>
            <ID>2</ID>
            <Name>Red Truck</Name>
        </truck>
    </trucks>
</body>
</document>

文件 3 示例

<?xml version="1.0" encoding="utf-8"?>
<document>
<header>
    <Date>03/02/2020</Date>
</header>
<body>
    <cars>
        <car>
            <ID>1</ID>
            <Name>Blue Car</Name>
        </car>
        <car>
            <ID>2</ID>
            <Name>Red Car</Name>
        </car>
    </cars>
    <trucks>
        <truck>
            <ID>1</ID>
            <Name>Blue Truck</Name>
        </truck>
        <truck>
            <ID>2</ID>
            <Name>Red Truck</Name>
        </truck>
    </trucks>
</body>
</document>

【问题讨论】:

  • 可以分享一下你试过的C#代码吗?
  • 将卡车反序列化为匹配类的一个实例,然后将汽车反序列化为第二个实例。最后,有第三个实例,您将实例 1 中的卡车和实例 2 中的汽车分配到该实例中(请记住,您正在执行引用类型分配,而不是深度复制,因此它不会太昂贵)。最后将第三个实例序列化为 XML

标签: c# xml nodes


【解决方案1】:

使用 XSLT:

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="*">
    <xsl:copy><xsl:apply-templates/></xsl:copy>
  </xsl:template>
  <xsl:template match="cars">
    <cars>
      <xsl:copy-of select="car"/>
      <xsl:copy-of select="document('other-doc.xml')//car"/>
    </cars>
  </xsl:template>
  <xsl:template match="trucks">
    <trucks>
      <xsl:copy-of select="truck"/>
      <xsl:copy-of select="document('other-doc.xml')//truck"/>
    </trucks>
  </xsl:template>
</xsl:transform>

这当然可以很容易地从 C# 使用 System.Xml.Xsl 处理器运行。

我没有尝试对标题中的日期做任何事情,因为我不确定你的逻辑是什么,但这很容易添加。

如果您想使用更高版本的 XSLT,它会变得更短一些,但您需要安装第三方库:

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:mode on-no-match="shallow-copy"/>
  <xsl:template match="cars">
    <cars>
      <xsl:copy-of select="car, doc('other-doc.xml')//car"/>
    </cars>
  </xsl:template>
  <xsl:template match="trucks">
    <trucks>
      <xsl:copy-of select="truck, doc('other-doc.xml')//truck"/>
    </trucks>
  </xsl:template>
</xsl:transform> 

【讨论】:

  • 这很好用,但是输出文档有奇怪的换行符,例如“卡车”标签在同一行中关闭和打开另一个, 标签与 xml 版本> 行。
  • 你可以用&lt;xsl:strip-space elements="*"/&gt;解决这个问题
【解决方案2】:
Please use below code 
 string xml1 = @"<document><header><startDate>01/01/2020</startDate><endDate> 01/02/ 2020</endDate></header><body><cars><car><ID>1</ID><Name>Blue Car</Name></car><car><ID>2</ID><Name>Red Car</Name></car></cars><trucks></trucks></body></document>";
            //load xml in StringReader
            StringReader sr = new StringReader(xml1);
            DataSet ds1 = new DataSet();
            // Read XML in ds1
            ds1.ReadXml(sr);

            string xml2 = @"<document><header><startDate> 01 / 01 / 2020 </startDate><endDate> 01 / 02 / 2020</endDate></header><body><cars></cars><trucks><truck><ID> 1 </ID><Name> Blue Truck </Name></truck><truck><ID>2</ID><Name>Red Truck</Name></truck></trucks></body></document>";
            sr = new StringReader(xml2);
            DataSet ds2 = new DataSet();
            ds2.ReadXml(sr);
            DataSet dsHeaders = new DataSet();
            dsHeaders.Tables.Add(ds1.Tables[0].Copy());
            string headersXML = dsHeaders.GetXml();
            headersXML = headersXML.Replace("<NewDataSet>", "").Replace("</NewDataSet>", "");
            //  Console.WriteLine(headersXML.Trim());
            DataSet dsCars = new DataSet("Cars");
            dsCars.Tables.Add(ds1.Tables[3].Copy());
            string carsXML = dsCars.GetXml();
            //    Console.WriteLine(carsXML);
            DataSet dsTrucks = new DataSet("Trucks");
            dsTrucks.Tables.Add(ds2.Tables[3].Copy());
            string trucksXML = dsTrucks.GetXml();
            //  Console.WriteLine(trucksXML);
            string resultXML = @"<document>" + headersXML + "<body>" + Environment.NewLine + carsXML + trucksXML + Environment.NewLine + "</body>" + Environment.NewLine + "</document>";
            Console.WriteLine(resultXML);


Your required XML
    <document>
      <header>
        <startDate>01/01/2020</startDate>
        <endDate> 01/02/ 2020</endDate>
      </header>
    <body>
    <Cars>
      <car>
        <ID>1</ID>
        <Name>Blue Car</Name>
      </car>
      <car>
        <ID>2</ID>
        <Name>Red Car</Name>
      </car>
    </Cars><Trucks>
      <truck>
        <ID> 1 </ID>
        <Name> Blue Truck </Name>
      </truck>
      <truck>
        <ID>2</ID>
        <Name>Red Truck</Name>
      </truck>
    </Trucks>
    </body>
    </document>

【讨论】:

    【解决方案3】:

    使用 xml linq:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace ConsoleApplication2
    {
        class Program
        {
            const string FILE1 = @"c:\TEMP\TEST.XML";
            const string FILE2 = @"c:\TEMP\TEST1.XML";
            static void Main(string[] args)
            {
                string xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><document></document>";
                XDocument doc3 = XDocument.Parse(xml);
                XElement doc = doc3.Root;
                doc.Add(new XElement("header", new XElement("Date", DateTime.Now.ToString("mm/dd/yyyy"))));
    
                XDocument doc1 = XDocument.Load(FILE1);
                XDocument doc2 = XDocument.Load(FILE2);
    
                XElement body = new XElement("body");
                doc.Add(body);
    
                XElement cars = new XElement("cars");
                body.Add(cars);
    
                List<XElement> cars1 = doc1.Descendants("car").ToList();
                cars.Add(cars1);
                List<XElement> cars2 = doc2.Descendants("car").ToList();
                cars.Add(cars2);
    
                XElement trucks = new XElement("trucks");
                body.Add(trucks);
    
                List<XElement> trucks1 = doc1.Descendants("truck").ToList();
                trucks.Add(trucks1);
                List<XElement> trucks2 = doc2.Descendants("truck").ToList();
                trucks.Add(trucks2);
    
            }
        }
    }
      
    

    【讨论】:

    • 这也很好用,但是“body”只做一个自闭标签。
    • 我将卡片和卡车添加到文档而不是正文。有新行:body.Add(cars); body.Add(卡车);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 2022-10-17
    • 2016-01-25
    • 2021-01-22
    相关资源
    最近更新 更多