Как полностью заменить один из узлов новыми данными в файле фрагмента xml? - PullRequest
1 голос
/ 11 февраля 2020

Я новый пользователь на этом форуме и не очень опытный разработчик / программист. Прежде чем задать этот вопрос, я искал и просматривал переполнение стека, и некоторые Microsoft предложили ссылки, но я не нашел то, что искал.

У меня есть следующий файл XML:

<?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>

Мне нужно заменить весь узел <DirProfiles>. Входящий узел может быть пустым, который выглядит как <DirProfiles />. Новый узел, который я хочу вставить, имеет формат:

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

Я попытался решить проблему как простую замену строки, но не получил нужный мне результат.

Редактировать: Мои извинения, я не понял, что мой файл xml является фрагментом xml документа и не является полным XML согласно спецификации c.

Ответы [ 3 ]

2 голосов
/ 11 февраля 2020

Учитывая, что ваш входной файл является искаженным XML файлом, который не содержит узла root, вы можете обойти это с небольшим количеством манипуляций со строками.

Вот файл, который вы говорите, что у вас есть :

<?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>

Вот как с этим работать:

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")));

Это дает мне:

<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>
1 голос
/ 11 февраля 2020

См. Следующее:

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");

        }
    }
}
0 голосов
/ 11 февраля 2020

Вы можете выполнить синтаксический анализ данных XML в модели класса C#, и после этого они могут выполнять изменения данных в соответствии с требованиями. После изменений вы можете снова проанализировать объект модели в XML и переписать строку XML в том же файле.

См. Эту ссылку для создания структуры класса по доступным XML: https://www.c-sharpcorner.com/blogs/convert-xml-json-file-to-c-sharp-class

И используйте этот код для преобразования Xml в C# объект класса

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;
    }

Вызов функции как:

var entity = ConvertXmlToObject<ModelClass>(XMLString);

Используйте этот код, чтобы снова преобразовать объект в 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;
        }

Вызовите эту функцию как:

string xmlString = ConvertObjectToXML<ModelClass>(ModelClassObject);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...