Soy totalmente nuevo en C #. Tengo que escribir un archivo xml que se parece de manera similar.

<DATA_SET SampleSize="5"> 
<DATA SampleID="1" IW="0.889" SL="24.24" PO="117" /> 
<DATA SampleID="2" IW="0.896" SL="24.41" PO="119" /> 
<DATA SampleID="3" IW="0.922" SL="24.3" PO="125" /> 
<DATA SampleID="4" IW="0.94" SL="24.24" PO="129" /> 
<DATA SampleID="5" IW="0.987" SL="24.32" PO="127" /> 
</DATA_SET>

Lo que tengo que intentar es

if (oneSet.Length == 5)
{
    qtm.SampleID = oneSet[0];//ROD
    qtm.SL = oneSet[1];//SIZEmmL
    qtm.SY = oneSet[2];//OVALmm
    qtm.RP = oneSet[3];//ROUND%
    qtm.VN = oneSet[4];//VENT%
    lstQTM.Add(qtm);
    isSet = true;
}

Aquí QTM es una clase, a través de esta clase he hecho una lista. SampleID, SL, SY, RP, VN son los métodos del archivo de clase QTM. Al usar el código anterior, los agregué a una lista.

using (FileStream fs = new FileStream("D:\\B.xml", FileMode.Create))
{
 new XmlSerializer(typeof(List<QTM>)).Serialize(fs, lstQTM);
}

Mi salida es

  <QTM>
    <SampleID>ROD</SampleID>
    <SL>WTg</SL>
    <SY>SIZEmmL</SY>
    <RP>OVALmm</RP>
    <VN>PDmm</VN>
  </QTM>
  <QTM>
    <SampleID>1</SampleID>
    <SL>0.740</SL>
    <SY>23.94</SY>
    <RP>0.28</RP>
    <VN>357</VN>
  </QTM>
  <QTM>
    <SampleID>2</SampleID>
    <SL>0.751</SL>
    <SY>23.98</SY>
    <RP>0.29</RP>
    <VN>368</VN>
  </QTM>
  <QTM>
    <SampleID>3</SampleID>
    <SL>0.733</SL>
    <SY>23.95</SY>
    <RP>0.39</RP>
    <VN>351</VN>
  </QTM>
  <QTM>
    <SampleID>4</SampleID>
    <SL>0.747</SL>
    <SY>23.99</SY>
    <RP>0.32</RP>
    <VN>363</VN>
  </QTM>
  <QTM>
    <SampleID>5</SampleID>
    <SL>0.734</SL>
    <SY>23.96</SY>
    <RP>0.23</RP>
    <VN>356</VN>
  </QTM>
  <QTM>
    <SampleID>6</SampleID>
    <SL>0.742</SL>
    <SY>23.89</SY>
    <RP>0.64</RP>
    <VN>365</VN>
  </QTM>
</ArrayOfQTM>

Cómo puedo hacer esto. ¿podría darme alguna idea?

c#
0
Arebhy Sridaran 10 may. 2019 a las 14:17

3 respuestas

La mejor respuesta

Aquí hay una estructura de clase de ejemplo que conserva la estructura de la clase QTM que ya tiene, pero que aún le da el XML que desea obtener.

[XmlRoot("DATA_SET")]
public class QTMCollection
{
    [XmlElement("DATA")]
    public List<QTM> QTMs { get; set; }

    [XmlAttribute("SampleSize")]
    public int SampleSize { get { return QTMs.Count; } set { return; } }        
}

public class QTM
{
    [XmlAttribute]
    public int SampleId { get; set; }
    [XmlAttribute]
    public decimal IW { get; set; }
    [XmlAttribute]
    public decimal SL { get; set; }
    [XmlAttribute]
    public int PO { get; set; }        
}

Necesitamos una estructura de clase externa aquí, impulsada principalmente por el atributo SampleSize en el elemento externo DATA_SET, de lo contrario no tendríamos que tenerla.

Aquí hay algunas peculiaridades: XmlSerializer solo serializará las propiedades que tienen un captador y configurador, por lo que tengo el configurador innecesario en SampleSize. Los XmlRoot, XmlAttribute y XmlElement sirven para decirle al serializador cómo llamar a sus clases y propiedades en el XML.

Aquí hay un ejemplo de cómo invocar el serializador para obtener un xem exactamente como su ejemplo:

QTMCollection collection = new ConsoleApplication135.QTMCollection()
{
    QTMs = new List<QTM>
    {
        new QTM() { SampleId = 1, IW = 0.0889M, SL = 24.24M, PO = 117 },
        new QTM() { SampleId = 2, IW = 0.896M, SL = 24.41M, PO = 119 },
        new QTM() { SampleId = 3, IW = 0.922M, SL = 24.3M, PO = 125 },
        new QTM() { SampleId = 4, IW = 0.94M, SL = 24.24M, PO = 129 },
        new QTM() { SampleId = 5, IW = 0.987M, SL = 24.32M, PO = 127 }
    }
};            

using (FileStream fileStream = new FileStream(@"c:\temp\B.xml", FileMode.Create))
{                
    using (var writer = XmlWriter.Create(fileStream, new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true }))
    {
        var serializer = new XmlSerializer(typeof(QTMCollection));
        serializer.Serialize(writer, collection, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
    }
}

La razón para usar XmlWriterSettings (y, por lo tanto, XmlWriter) aquí es omitir la declaración Xml en la parte superior del XML que de otro modo aparecería:

<?xml version="1.0" encoding="utf-8"?>

Y el propósito de esto:

new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty })

Es evitar la declaración de espacio de nombres predeterminada en el elemento raíz que de otro modo aparecería:

<DATA_SET xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SampleSize="5">

Mientras que con ambas cosas, la salida será un XML sin adornos como este:

<DATA_SET SampleSize="5">
  <DATA SampleId="1" IW="0.0889" SL="24.24" PO="117" />
  <DATA SampleId="2" IW="0.896" SL="24.41" PO="119" />
  <DATA SampleId="3" IW="0.922" SL="24.3" PO="125" />
  <DATA SampleId="4" IW="0.94" SL="24.24" PO="129" />
  <DATA SampleId="5" IW="0.987" SL="24.32" PO="127" />
</DATA_SET>
1
steve16351 10 may. 2019 a las 11:57

En sus clases de C #, puede agregar atributos a sus variables miembro que cambiarán el comportamiento de XmlSerializer. Por ejemplo, lo siguiente hará que el SampleID se serialice como un atributo en lugar de un elemento:

public class QTM {
    [XmlAttribute("SampleID")]
    public int SampleID;
}

Consulte la documentación para obtener más información aquí

1
kevernicus 10 may. 2019 a las 11:29

Actualizar

Como señaló Rand Random , leí mal la pregunta original. Por lo tanto, sea consciente de ello. Cito el comentario para referencia futura.

Como se observa en el comentario, el OP es consciente del mecanismo, pero no sabía que necesita un objeto raíz y que puede cambiar un XmlElement a XmlAttribute declarándolo con atributos

Si desea leer un documento XML sin ensuciarse las manos, puede usar XmlSerializer.

Es super fácil. Primero crea POCO (clases con solo propiedades) que imitan el archivo XML que desea leer. Comience desde la raíz:

[XmlRoot("DATA_SET ")]
public sealed class MyRoot
{
    [XmlElement("sampleSize")]
    public int SampleSize { get; set; }

    [XmlArrayItem("data")]
    public List<MyData> Data { get; set; }

}

El código anterior modela la raíz. Es lo más detallado posible para comprender lo que efectivamente está haciendo.

Luego, modela el nodo interno:

[Serializable]
public sealed class MyData
{
    [XmlAttribute("SampleID")]
    public int SampleId { get; set; }

    [XmlAttribute("IW")]
    public double WhateverThisIs1 { get; set; }

    [XmlAttribute("SL")]
    public double WhateverThisIs2 { get; set; }

    [XmlAttribute("PO")]
    public int WhateverThisIs3 { get; set; }
}

El código anterior declara las propiedades con los nombres que desea en C #, asignados a los nombres que espera en su archivo xml. Como puede ver, difieren.

Finalmente, puede leer su archivo de esta manera:

var serializer = new XmlSerializer(typeof(MyRoot));

using (var reader = new StreamReader(fileName))
{
    var root = (MyRoot)serializer.Deserialize(reader);
    // do something with root.
}

Nota: Puede que tenga que ajustar el nodo raíz para manejar adecuadamente su nodo secundario, en caso de que la jerarquía sea más compleja.

Puede leer más en MSDN

1
Yennefer 10 may. 2019 a las 14:10