Sr.SoftwareDev Ответов: 1

Как разобрать XML-данные в свойства объекта C#


У меня есть XML-данные, которые я хочу преобразовать в свойства объекта C#. Я пробовал десериализацию,но она не отделяет имя и значение в свойствах.

Пример XML:

& lt;?xml version=" 1.0 "encoding=" UTF-8"?>
&ЛТ;xfdf префиксом xmlns="http://ns.adobe.com/xfdf/ от" XML:пространство="сохранить"и GT;
& lt;поля>
< field name= "название компании">
< value & gt;ABC

< имя поля= "адрес компании">
<value & gt;Чикаго

< имя поля= "телефон компании">
< значение> 123-456-7894

< имя поля= "ACSysHP_ASHP_135k_240k_MeasureID">
< значение & gt;2635




Что я уже пробовал:

Это мой основной класс:

mespace TestApp
{
    [XmlTypeAttribute]
    [XmlRootAttribute("xfdf", Namespace = "http://ns.adobe.com/xfdf/")]
    public class XFDF
    {
        [XmlElementAttribute("fields")]
        public Fields fields { get; set; }
    }

    public class Fields
    {
        public Fields()
        {
            field = new List<Field>();
        }
        [XmlElement(ElementName = "field")]
        public List<Field> field { get; set; }
        
    }

    [XmlRoot(ElementName = "field")]
    // [XmlTypeAttribute]
    public class Field
    {
        // "Company City"

        [XmlAttribute("name")]
        public string Name { get; set; }

        [XmlElementAttribute("value")]
        public string value { get; set; }

    }
}




Это код формы:

private void button1_Click(object sender, EventArgs e)
        {

            string path = string.Empty;

            path = Directory.GetCurrentDirectory() + @"\XML\Application 1-16-17_data_030617.xml";

            string xData = File.ReadAllText(path);

            var deserializer = new XmlSerializer(typeof(XFDF));
            using (var reader = XmlReader.Create(new StringReader(xData)))
            {
                XFDF test = (XFDF)deserializer.Deserialize(reader);
               // MessageBox.Show("Field Name: " + test.fields[0].field[1885].Name + Environment.NewLine + " value:" + test.fields[0].field[1885].value);
            }
                


        }



Это дает вам результат как:
Имя Поля: Название Компании
значение: ABC
Имя Поля: Адрес Компании
значение: Чикаго

В настоящее время у моего класса есть подкласс под названием Field, и он имеет 2 свойства Name и Value: то, что я хочу, - это иметь свойство CompanyName, и когда я вызываю это свойство из Form1, я должен дать мне "ABC".

1 Ответов

Рейтинг:
1

David_Wimbley

Я не уверен, что это результат плохого форматирования, но ваш код и XML имеют довольно много проблем. XML-файл искажен, правильно отформатирован будет

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
	<fields>
		<field name="Company Name">
			<value>ABC</value>
		</field>
		<field name="Company Address">
			<value>Chicago</value>
		</field>
		<field name="Company phone">
			<value>123-456-7894</value>
		</field>
		<field name="ACSysHP_ASHP_135k_240k_MeasureID">
			<value>2635</value>
		</field>
	</fields>
</xfdf>


И если вы сериализуете, то правильная структура класса/нотация будет следующей (Примечание: я использовал Xml2CSharp.com / преобразуйте ваши XML-примеры в совместимые с XmlSerializer классы C# [^] чтобы преобразовать XML в классы c# для меня)

[XmlRoot(ElementName="field", Namespace="http://ns.adobe.com/xfdf/")]
public class Field {
	[XmlElement(ElementName="value", Namespace="http://ns.adobe.com/xfdf/")]
	public string Value { get; set; }
	[XmlAttribute(AttributeName="name")]
	public string Name { get; set; }
}

[XmlRoot(ElementName="fields", Namespace="http://ns.adobe.com/xfdf/")]
public class Fields {
	[XmlElement(ElementName="field", Namespace="http://ns.adobe.com/xfdf/")]
	public List<Field> Field { get; set; }
}

[XmlRoot(ElementName="xfdf", Namespace="http://ns.adobe.com/xfdf/")]
public class Xfdf {
	[XmlElement(ElementName="fields", Namespace="http://ns.adobe.com/xfdf/")]
	public Fields Fields { get; set; }
	[XmlAttribute(AttributeName="xmlns")]
	public string Xmlns { get; set; }
	[XmlAttribute(AttributeName="space", Namespace="http://www.w3.org/XML/1998/namespace")]
	public string Space { get; set; }
}


Затем, чтобы десериализовать ваш XML в объекты C#, вы бы сделали

var stream = new MemoryStream();
           var writer = new StreamWriter(stream);
           writer.Write(xml);
           writer.Flush();
           stream.Position = 0;

           var reader = XmlReader.Create(stream, new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document });
           var myXmlObject = new XmlSerializer(typeof(Xfdf)).Deserialize(reader) as Xfdf;



Поэтому, как только вы десриализовали свой код, вы можете зациклиться на нем следующим образом

foreach (var item in myXmlObject.Fields.Field)
            {
                Console.WriteLine("Field Name {0} - Field Value {1}", item.Name, item.Value);
            }



Что обеспечивает выход

Цитата:
Наименование поля Название компании - АВС поле Значение
Имя Поля Адрес Компании - Значение Поля Чикаго
Поля Имя, Телефон компании - значение поля 123-456-7894
Имя Поля ACSysHP_ASHP_135k_240k_MeasureID - Значение Поля 2635



РЕДАКТИРОВАТЬ:

Измененный XML для поддержки новых имен полей/свойств

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
	<fields>
		<field>
			<CompanyName>ABC</CompanyName>
			<CompanyPhoneNumber>ABC</CompanyPhoneNumber>
			<CompanyAddress>ABC</CompanyAddress>
		</field>
		<field>
			<CompanyName>ABC</CompanyName>
			<CompanyPhoneNumber>ABC</CompanyPhoneNumber>
			<CompanyAddress>ABC</CompanyAddress>
		</field>
		<field>
			<CompanyName>ABC</CompanyName>
			<CompanyPhoneNumber>ABC</CompanyPhoneNumber>
			<CompanyAddress>ABC</CompanyAddress>
		</field>
		<field>
			<CompanyName>ABC</CompanyName>
			<CompanyPhoneNumber>ABC</CompanyPhoneNumber>
			<CompanyAddress>ABC</CompanyAddress>
		</field>
	</fields>
</xfdf>


Измененный класс полей для сериализации

[XmlRoot(ElementName="field", Namespace="http://ns.adobe.com/xfdf/")]
public class Field {
	[XmlElement(ElementName="CompanyName", Namespace="http://ns.adobe.com/xfdf/")]
	public string CompanyName { get; set; }
	[XmlElement(ElementName="CompanyPhoneNumber", Namespace="http://ns.adobe.com/xfdf/")]
	public string CompanyPhoneNumber { get; set; }
	[XmlElement(ElementName="CompanyAddress", Namespace="http://ns.adobe.com/xfdf/")]
	public string CompanyAddress { get; set; }
}


Что тогда позволит вам сделать

foreach (var item in myXmlObject.Fields.Field)
{
	Console.WriteLine("CompanyName: {0}", item.CompanyName);
	Console.WriteLine("CompanyAddress: {0}", item.CompanyAddress);
	Console.WriteLine("CompanyPhoneNumber: {0}", item.CompanyPhoneNumber);
}


Sr.SoftwareDev

Да, XML здесь отформатирован неправильно, у меня правильный формат. Проблема заключается в том, что в классе полей мне нужны свойства CompanyName, companyAddress, CompanyPhone. Что должно дать мне значение этих свойств (имя поля). Например, в вашем коде я хочу элемент.Companyname и должен вернуть меня
АЗБУКА.

David_Wimbley

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

Но, исходя из того, что я понимаю, вы хотите сделать, вышеприведенная правка должна достичь этого.

Sr.SoftwareDev

Я не могу изменить формат XML, так как получаю этот формат от заказчика. Я должен использовать этот формат XML и должен анализировать объект со свойствами. Я перепробовал все возможные вещи, я думаю, что не могу просто сделать это в свойствах его самого. Я должен идти по имени и ценить себя.

Спасибо за ваш ответ.

David_Wimbley

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

Экс:


var myData = new List<ProperFormattedXmlClass>();


foreach(var item in myXmlObject.Fields.Field)
{
    var data = new ProperFormattedXmlClass();
    if(item.Name == "Company Name")
    {
       //Assign  company name value here to .CompanyName from my class
       data.CompanyName = item.Value;
    }
}