简体   繁体   中英

How can I replace completely one of nodes with new data within fragment xml file?

I am a new user on this forum and I'm not a highly experienced developer/programmer. Before asking this question, I searched and looked through Stack Overflow and some Microsoft suggested links, but I didn't find what I was looking for.

I've got the following XML file:

<?xml version="1.0" standalone="no" ?>
<WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
<LayerManager />
<ViewLayers name="RoofLayout" roof="1" nlwalls="1">
    <Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
</ViewLayers>
<DirProfiles>
    <ProfileInfo ProfileName="ControlCQFT" JobPath="C:\Jobs" DatabasePath="D:\Database\ControlCQFT" />
</DirProfiles>
<DirHistory>
     <ProfileInfo Use="Job" Path="C:\Jobs" />
</DirHistory>

I need to replace the entire <DirProfiles> node. The incoming node can be empty, which looks like <DirProfiles /> . The new node that I want to insert is in the format:

<DirProfiles> 
      <ProfileInfo ProfileName="Control1" JobPath="D:\Client1\JobsA" DatabasePath="D:\Database\Control1" />
. . . . .
</DirProfiles>

I tried to handle the problem as a simple string replacement, but I didn't get the result that I needed.

Edit: My apology, I didn't realized that my xml file is fragment xml document and not full XML as per spec.

Given your input file is a malformed XML file that doesn't contain a root node, you can get around this with a bit of string manipulation.

Here's the file you say you have:

<?xml version="1.0" standalone="no" ?>
<WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
<LayerManager />
<ViewLayers name="RoofLayout" roof="1" nlwalls="1">
    <Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
</ViewLayers>
<DirProfiles>
    <ProfileInfo ProfileName="ControlCQFT" JobPath="C:\Jobs" DatabasePath="D:\Database\ControlCQFT" />
</DirProfiles>
<DirHistory>
     <ProfileInfo Use="Job" Path="C:\Jobs" />
</DirHistory>

Here's how to work with it:

var sourceFileName = @"C:\{path}\xml_fragments.txt";

var text = $"<root>{String.Join(Environment.NewLine, File.ReadLines(sourceFileName).Skip(1))}</root>";

var doc = XDocument.Parse(text);

doc.Root.Element("DirProfiles").Elements().Remove();

doc.Root.Element("DirProfiles").Add(
    new XElement(
        "ProfileInfo",
        new XAttribute("ProfileName", "Control1"),
        new XAttribute("JobPath", @"D:\Client1\JobsA"),
        new XAttribute("DatabasePath", @"D:\Database\Control1")));

That gives me:

<root>
  <WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
  <LayerManager />
  <ViewLayers name="RoofLayout" roof="1" nlwalls="1">
    <Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
  </ViewLayers>
  <DirProfiles>
    <ProfileInfo ProfileName="Control1" JobPath="D:\Client1\JobsA" DatabasePath="D:\Database\Control1" />
  </DirProfiles>
  <DirHistory>
    <ProfileInfo Use="Job" Path="C:\Jobs" />
  </DirHistory>
</root>

See following :

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 FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            string xml = File.ReadAllText(FILENAME);
            XElement doc = new XElement("Root");
            doc.Add(XElement.Parse(xml));

            XElement dirProfiles = doc.Descendants("DirProfiles").FirstOrDefault();

            XElement profileInfo = dirProfiles.Element("ProfileInfo");
            profileInfo.SetAttributeValue("ProfileName", "Control1");
            profileInfo.SetAttributeValue("JobPath", @"D:\Client1\JobsA");
            profileInfo.SetAttributeValue("DatabasePath", @"D:\Database\Control1");

        }
    }
}

You can parse the XML data to a C# class model, and after that could do the data changes as per requirement. After changes, you can again parse the model object to XML and rewrite the XML string on the same file.

Refer this link for generate a class structure by available XML: https://www.c-sharpcorner.com/blogs/convert-xml-json-file-to-c-sharp-class

And Use this code to Convert Xml to a C# class object

public static T ConvertXmlToObject<T>(String xml)
    {
        T result = default(T);

        try
        {
            using (TextReader reader = new StringReader(xml))
            {
                try
                {
                    result =
                        (T)new XmlSerializer(typeof(T)).Deserialize(reader);
                }
                catch (InvalidOperationException)
                {
                    // Throw message for invalid XML
                }
            }
        }
        catch (Exception ex)
        {
        }

        return result;
    }

Call the function like :

var entity = ConvertXmlToObject<ModelClass>(XMLString);

User this code to convert again Object to XML

public static string ConvertObjectToXML<T>(T ModelClass)
        {
            XmlSerializer xsObject = new XmlSerializer(typeof(T));
            var inputObject = ModelClass;
            var xmlString = "";

            using (var sw = new StringWriter())
            {
                using (XmlWriter writer = XmlWriter.Create(sw))
                {
                    xsObject.Serialize(writer, inputObject);
                    xmlString = sw.ToString();
                }
            }

            return xmlString;
        }

Call this function like :

string xmlString = ConvertObjectToXML<ModelClass>(ModelClassObject);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM