【问题标题】:How do you create XML document from reading another XML file using C#?如何使用 C# 通过读取另一个 XML 文件来创建 XML 文档?
【发布时间】: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,这种事情要容易得多。

标签: c# xml dom xmldom


【解决方案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 框架的一部分。那么有什么问题呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-02
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多