Проблема преобразования XML в Json и DeserializeObject - пространства имен InfoPath?

Я собираюсь загрузить большое количество XML-файлов InfoPath в Cosmos DB в виде файлов Json для тестирования возможного проекта. Но мне трудно преобразовать файлы XML в Json, а затем загрузить обратно в класс C#. Я думаю, что это связано с пространством имен, которое InfoPath помещает в XML, но я не уверен. Сначала я подумал, что мне нужно попытаться удалить все ссылки на пространства имен из XML, но теперь мне интересно, нужно ли мне просто больше поработать над определением файла класса. Для создания файла класса я использовал Visual Studio «вставить как Json». Я предположил, что после загрузки XML, сохранения в Json, а затем использования этого в качестве основы для нового файла класса я могу загрузить его обратно в объект, но когда я вызываю DeserializeObject, он всегда заканчивается нулевым.

Это потому, что необходимо изменить определение файла класса, или мне лучше попытаться очистить XML перед преобразованием в Json?

Образец XML

<?xml version = "1.0" encoding = "utf-8"?>
<?mso-infoPathSolution name = "urn:schemas-microsoft-com:office:infopath:myProject:-myXSD-2017-05-05T14-19-13" solutionVersion = "1.0.0.2046" productVersion = "16.0.0.0" PIVersion = "1.0.0.0" href = "https://myportal.sharepoint.com/sites/mySite/myProject/Forms/template.xsn"?>
<?mso-application progid = "InfoPath.Document" versionProgid = "InfoPath.Document.4"?>
<?mso-infoPath-file-attachment-present?>
<my:myFields xmlns:my = "http://schemas.microsoft.com/office/infopath/2003/myXSD/2017-05-05T14:19:13" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml = "http://www.w3.org/1999/xhtml" xmlns:pc = "http://schemas.microsoft.com/office/infopath/2007/PartnerControls" xmlns:ma = "http://schemas.microsoft.com/office/2009/metadata/properties/metaAttributes" xmlns:d = "http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields" xmlns:q = "http://schemas.microsoft.com/office/infopath/2009/WSSList/queryFields" xmlns:dfs = "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:dms = "http://schemas.microsoft.com/office/2009/documentManagement/types" xmlns:tns = "http://microsoft.com/webservices/SharePointPortalServer/UserProfileService" xmlns:s1 = "http://microsoft.com/wsdl/types/" xmlns:http = "http://schemas.xmlsoap.org/wsdl/http/" xmlns:tm = "http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc = "http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime = "http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap12 = "http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsdl = "http://schemas.xmlsoap.org/wsdl/" xmlns:xd = "http://schemas.microsoft.com/office/infopath/2003" xml:lang = "en-US">
    <my:Admin>
        <my:Routing_Order>
            <my:Approver-1_Order>1</my:Approver-1_Order>
            <my:Approver-2_Order>5</my:Approver-2_Order>
            <my:Approver-3_Order>4</my:Approver-3_Order>
        </my:Routing_Order>
    </my:Admin>
    <my:Request_Status>Save as Draft</my:Request_Status>
    <my:Request_Type>CAPEX</my:Request_Type>
</my:myFields>

Файл класса

namespace xml_to_json
{

    public class Rootobject
    {
        public MyMyfields mymyFields { get; set; }
    }

    public class MyMyfields
    {
        public string xmlnsmy { get; set; }
        public string xmlnsxsi { get; set; }
        public string xmlnsxhtml { get; set; }
        public string xmlnspc { get; set; }
        public string xmlnsma { get; set; }
        public string xmlnsd { get; set; }
        public string xmlnsq { get; set; }
        public string xmlnsdfs { get; set; }
        public string xmlnsdms { get; set; }
        public string xmlnstns { get; set; }
        public string xmlnss1 { get; set; }
        public string xmlnshttp { get; set; }
        public string xmlnstm { get; set; }
        public string xmlnssoap { get; set; }
        public string xmlnssoapenc { get; set; }
        public string xmlnsmime { get; set; }
        public string xmlnssoap12 { get; set; }
        public string xmlnswsdl { get; set; }
        public string xmlnsxd { get; set; }
        public string xmllang { get; set; }
        public MyAdmin myAdmin { get; set; }
        public string myRequest_Status { get; set; }
        public string myRequest_Type { get; set; }
    }

    public class MyAdmin
    {
        public MyRouting_Order myRouting_Order { get; set; }
    }

    public class MyRouting_Order
    {
        public string myApprover1_Order { get; set; }
        public string myApprover2_Order { get; set; }
        public string myApprover3_Order { get; set; }
    }


}

Код теста консоли

namespace xml_to_json
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument myDoc = new XmlDocument();
            string sourcedir = @"C:\Users\mystuff\Downloads\test-clean\";
            string xmlfilein = @"test";
            string xmlfile = string.Concat(sourcedir, xmlfilein, ".xml");
            string jsonfileout = string.Concat(sourcedir, xmlfilein, ".json");
            myDoc.Load(xmlfile);
            string jsonText = JsonConvert.SerializeXmlNode(myDoc.LastChild);
            File.WriteAllText(jsonfileout, jsonText);

            Rootobject obj = new Rootobject();
            obj = JsonConvert.DeserializeObject<Rootobject>(jsonText);
            Console.WriteLine(obj.mymyFields.myRequest_Status);   
        }   
    }
}

Почему бы не выполнить десериализацию напрямую с помощью XmlSerializer? Если вы используете XmlSerializer, вы можете полностью пропустить промежуточное представление JSON.

dbc 28.10.2018 20:37

Если я правильно понимаю вашу идею, цель состоит не в том, чтобы поместить XML-данные в объект. Цель состоит в том, чтобы преобразовать данные XML в формат Json, чтобы их можно было загрузить в Cosmos DB, а затем протестировать, используя этот документ Json в качестве объекта. Преобразование в Json - это не шаг, который я хочу пропустить, а часть процесса, которому мне нужно следовать.

pretzelb 29.10.2018 22:23

Хорошо, тогда зачем тебе Rootobject? После того, как у вас есть jsonText, вы преобразовали свои XML-данные в формат JSON и все готово, верно?

dbc 29.10.2018 22:36

RootObject был создан из команды вставки в Json, о которой я упоминал в моем первом посте. Я надеялся, что Visual Studio сможет сделать перевод за меня. Наличие файла Json - это часть шага. Я мог бы загрузить Cosmos DB. Однако следующим моим шагом будет чтение этого файла и загрузка его в объект, чтобы я мог протестировать создание пользовательского интерфейса для этих документов. Чем больше я исследую, тем больше я думаю, что мне нужно удалить пространства имен и другие директивы в XML, прежде чем я попытаюсь выполнить преобразование.

pretzelb 30.10.2018 00:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
213
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Попробуйте код ниже, используя xml linq:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            XElement routingOrder = doc.Descendants().Where(x => x.Name.LocalName == "Routing_Order").FirstOrDefault();

            Dictionary<string, string> orders = routingOrder.Elements()
                .GroupBy(x => x.Name.LocalName, y => (string)y)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

            string status = (string)doc.Descendants().Where(x => x.Name.LocalName == "Request_Status").FirstOrDefault();
            string requestType = (string)doc.Descendants().Where(x => x.Name.LocalName == "Request_Type").FirstOrDefault();
        }
    }
}

Я думаю, что мог бы сделать то же самое с XMLDocument и сопоставить путь к каждому узлу, но я больше искал способ заставить DeserializeObject работать без сопоставления каждого узла по отдельности. Возможно, я отредактирую исходный вопрос, чтобы больше сосредоточиться на том, как определить объект Json, когда задействовано пространство имен.

pretzelb 27.10.2018 16:22

Попробуйте сериализовать в файл, а затем десериализовать файл. Это покажет, верны ли определения классов. Тогда вы узнаете, в чем проблема: в классах или в json.

jdweng 27.10.2018 16:43

Использование предложения от jdweng и XDocument помогло очистить файл XML для облегчения перехода на Json. Ниже приведен пример кода, который я использовал для очистки документа.

    XDocument newxdoc = XDocument.Load(xmlfile);
    newxdoc.DescendantNodes().Where(e => e.NodeType.ToString().StartsWith("ProcessingInstruction")).Remove();          
    string newstringdoc = RemoveAllNamespaces(newxdoc.ToString());
    newxdoc = XDocument.Parse(newstringdoc);

Другие вопросы по теме