如何使用 C# 通过读取另一个 XML 文件来创建 XML 文档?

Posted

技术标签:

【中文标题】如何使用 C# 通过读取另一个 XML 文件来创建 XML 文档?【英文标题】:How do you create XML document from reading another XML file using C#? 【发布时间】:2021-12-14 03:33:21 【问题描述】:

我正在尝试重新创建一个 xml 文档。 我正在阅读现有的 xml 文档,然后尝试使用 C# 重新创建它。

到目前为止,我能够阅读并创建新文档的外壳。

我正在遍历每个子节点并将其添加到产品节点。

我的 xml 文件(来源):

<?xml version="1.0" encoding="utf-8"?>
<DroneList>
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Phantom 3</modelName>
        <estimatedPrice>699</estimatedPrice>
        <flightTime>17 to 20</flightTime>
        <modelSize>Medium</modelSize>   
    </product>
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Inspire 1</modelName>
        <estimatedPrice>2899</estimatedPrice>
        <flightTime>18 to 20</flightTime>
        <modelSize>Large</modelSize>
    </product>
</DroneList>

注意:根目录下有多个具有唯一项的产品。

我使用 C# 程序的目标是能够:

从列表中读取现有产品 将它们添加到新的 xml 文档中 向新的 xml 文档添加新项目 将 xml 文档另存为新的 xml 文件

我的 C# 代码如下:

        private void btnChange_Click(object sender, EventArgs e)
        
            txtDisplay.Clear();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(XML_FILE_PATH); // load xml data
            XmlDocument newDoc = new XmlDocument(); // create a new xmldocument object to hold new xml data

            txtDisplay.Text += "****Reading Drone List**** \r\n";

            // loaded existing xml data
            XmlElement root = xmlDoc.DocumentElement;
            XmlNodeList children = root.ChildNodes;

            txtDisplay.Text += "****Showing Existing Data**** \r\n children: " + children.Count + "\r\n";

            for (int i = 0; i < children.Count; i++)
            
                XmlElement product = newDoc.CreateElement("product");
                product.SetAttribute("productId", i.ToString());

                foreach (XmlNode child in children)
                

                    XmlElement manufacturer = newDoc.CreateElement("manufacturer");
                    XmlElement modelName = newDoc.CreateElement("modelName");
                    XmlElement estimatedPrice = newDoc.CreateElement("estimatedPrice");
                    XmlElement flightTime = newDoc.CreateElement("flightTime");
                    XmlElement modelSize = newDoc.CreateElement("modelSize");

                    manufacturer.InnerText = child["manufacturer"].InnerText;
                    modelName.InnerText = child["modelName"].InnerText;
                    estimatedPrice.InnerText = child["estimatedPrice"].InnerText;
                    flightTime.InnerText = child["flightTime"].InnerText;
                    modelSize.InnerText = child["modelSize"].InnerText;

                    product.AppendChild(manufacturer);
                    product.AppendChild(modelName);
                    product.AppendChild(estimatedPrice);
                    product.AppendChild(flightTime);
                    product.AppendChild(modelSize);
                
            



            txtDisplay.Text += "****Showing new doc so far**** \r\n";

            txtDisplay.Text += newDoc.InnerXml + "\r\n"; // display xml in the textbox

            //txtDisplay.Text += newRoot.InnerText + "\r\n";

            txtDisplay.Text += "****Adding New Data**** \r\n";

            

            for (int i = 5; i < 5; i++)
            
                //
            

            XmlElement newRoot = newDoc.CreateElement("DroneList"); // the root element is <roster>
            newDoc.AppendChild(newRoot);
            XmlDeclaration xmlDec = newDoc.CreateXmlDeclaration("1.0", null, null);
            newDoc.InsertBefore(xmlDec, newRoot); // insert before the root element

            newDoc.Save("..\\..\\..\\new_drones.xml");

        

所需的 XML 结果:

新的 xml 文件(目标)

<?xml version="1.0" encoding="utf-8"?>
<DroneList>
    <!-- existing products from source file -->
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Phantom 3</modelName>
        <estimatedPrice>699</estimatedPrice>
        <flightTime>17 to 20</flightTime>
        <modelSize>Medium</modelSize>   
    </product>
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Inspire 1</modelName>
        <estimatedPrice>2899</estimatedPrice>
        <flightTime>18 to 20</flightTime>
        <modelSize>Large</modelSize>
    </product>
    <!-- new products added through C# program (Hard coded) -->
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Inspire 1</modelName>
        <estimatedPrice>2899</estimatedPrice>
        <flightTime>18 to 20</flightTime>
        <modelSize>Large</modelSize>
    </product>
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Inspire 1</modelName>
        <estimatedPrice>2899</estimatedPrice>
        <flightTime>18 to 20</flightTime>
        <modelSize>Large</modelSize>
    </product>
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Inspire 1</modelName>
        <estimatedPrice>2899</estimatedPrice>
        <flightTime>18 to 20</flightTime>
        <modelSize>Large</modelSize>
    </product>
</DroneList>

【问题讨论】:

请在您的问题中添加所需的输出 XML。总的来说,这听起来像是 XSLT 的一项任务。 如果是我,我会 (1) 反序列化为 c# 对象,(2) 编写代码以添加到对象的列表,(3) 反序列化回 xml。 @YitzhakKhabinsky 我已经用期望的结果更新了问题。 使用专为这项工作设计的 XSLT,这种事情要容易得多。 【参考方案1】:

总体而言,XSLT 的设计目的是将输入 XML 转换为输出 XML,或其他文本格式。

请尝试以下基于 XSLT 的解决方案。

XSLT 采用最后一个 product 元素并将其乘以 4 次。 输入 XML 的其余部分保持不变。

下面的 c# 代码是 XSLT 转换的通用样板代码。

输入 XML

<?xml version="1.0"?>
<DroneList>
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Phantom 3</modelName>
        <estimatedPrice>699</estimatedPrice>
        <flightTime>17 to 20</flightTime>
        <modelSize>Medium</modelSize>
    </product>
    <product>
        <manufacturer>DJI</manufacturer>
        <modelName>Inspire 1</modelName>
        <estimatedPrice>2899</estimatedPrice>
        <flightTime>18 to 20</flightTime>
        <modelSize>Large</modelSize>
    </product>
</DroneList>

XSLT 1.0

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="no"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="product[last()]">
        <xsl:variable name="product">
            <xsl:copy-of select="."/>
        </xsl:variable>

        <xsl:for-each select="(//node())[4 &gt;= position()]">
            <xsl:copy-of select="$product"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

输出 XML

<?xml version="1.0" encoding="utf-8"?>
<DroneList>
  <product>
    <manufacturer>DJI</manufacturer>
    <modelName>Phantom 3</modelName>
    <estimatedPrice>699</estimatedPrice>
    <flightTime>17 to 20</flightTime>
    <modelSize>Medium</modelSize>
  </product>
  <product>
    <manufacturer>DJI</manufacturer>
    <modelName>Inspire 1</modelName>
    <estimatedPrice>2899</estimatedPrice>
    <flightTime>18 to 20</flightTime>
    <modelSize>Large</modelSize>
  </product>
  <product>
    <manufacturer>DJI</manufacturer>
    <modelName>Inspire 1</modelName>
    <estimatedPrice>2899</estimatedPrice>
    <flightTime>18 to 20</flightTime>
    <modelSize>Large</modelSize>
  </product>
  <product>
    <manufacturer>DJI</manufacturer>
    <modelName>Inspire 1</modelName>
    <estimatedPrice>2899</estimatedPrice>
    <flightTime>18 to 20</flightTime>
    <modelSize>Large</modelSize>
  </product>
  <product>
    <manufacturer>DJI</manufacturer>
    <modelName>Inspire 1</modelName>
    <estimatedPrice>2899</estimatedPrice>
    <flightTime>18 to 20</flightTime>
    <modelSize>Large</modelSize>
  </product>
</DroneList>

c#

oid Main()

   const string SOURCEXMLFILE = @"e:\Temp\input.xml";
   const string XSLTFILE = @"e:\Temp\process.xslt";
   const string OUTPUTXMLFILE = @"e:\temp\output.xml";

   try
   
      XsltArgumentList xslArg = new XsltArgumentList();

      using (XmlReader src = XmlReader.Create(SOURCEXMLFILE))
      
         XslCompiledTransform xslt = new XslCompiledTransform();
         xslt.Load(XSLTFILE, new XsltSettings(true, true), new XmlUrlResolver());

         XmlWriterSettings settings = xslt.OutputSettings.Clone();
         settings.IndentChars = "\t";
         // to remove BOM
         settings.Encoding = new UTF8Encoding(false);

         using (XmlWriter result = XmlWriter.Create(OUTPUTXMLFILE, settings))
         
            xslt.Transform(src, xslArg, result, new XmlUrlResolver());
            result.Close();
         
      
      Console.WriteLine("File '0' has been generated.", OUTPUTXMLFILE);
   
   catch (Exception ex)
   
      Console.WriteLine(ex.Message);
   

【讨论】:

@Yizhak 我只需要使用 C# 执行此操作。我不能使用 XSLT 或除 XML DOM 之外的任何其他方法,也不能使用元素和节点系统地分解它。 XSLT 是 .Net 框架的一部分。那么有什么问题呢?

以上是关于如何使用 C# 通过读取另一个 XML 文件来创建 XML 文档?的主要内容,如果未能解决你的问题,请参考以下文章

用C#读取XML文件,怎么可以循环读取

如何通过使用 c# 传递凭据在服务器上创建文件夹

c# 中,如何读取XML文件,并将读取到的内容显示到TreeView中

c# winform读取xml文件创建菜单的代码

C# - 将数据写入流 + 使用另一个流读取数据

用 c# 创建 xml 文档并用 perl 解析它