how to generate an xml in memory

Asked

Viewed 961 times

3

With the code below, I Gero a file and write somewhere, however, instead of writing to the disk, I wanted to generate in memory, as it does?

 using (var context = new ClassContexto(ClassMaster.conexao()))
            {
                using (DbContextTransaction tran = context.Database.BeginTransaction(IsolationLevel.ReadCommitted))
                {
                    try
                    {
                        #region MyRegion
                        retorno = (from a in context.Inventario
                                   join c in context.Medicamento on a.t0051_id_medicamento equals c.t0051_id_medicamento
                                   where a.t0020_id_empresa == 1
                                   select new
                                   {
                                       c.t0051_tipo_subs,
                                       c.t0051_ms,
                                       a.t0061_lote,
                                       a.t0061_qtde,
                                       a.t0061_dt_lcto
                                   });
                        #endregion
                        XmlTextWriter writer = new XmlTextWriter(@"c:\lixos\filmes.xml", null);

                        //inicia o documento xml
                        writer.WriteStartDocument();
                        //escreve o elmento raiz
                        writer.WriteStartElement("mensagemSNGPCInventario");
                        writer.WriteAttributeString("xmlns", "urn:sngpc-schema");

                        writer.WriteRaw("<cabecalho>"
                            + "<cnpjEmissor>12935236000107</cnpjEmissor>"
                            + "<cpfTransmissor>01472346971</cpfTransmissor>"
                            + "<data>206-01-01</data>"
                            + "</cabecalho>");

                        writer.WriteStartElement("corpo");
                        writer.WriteStartElement("medicamentos");

                        foreach (var item in retorno)
                        {
                            //writer.WriteStartElement("entradaMedicamentos");
                            writer.WriteRaw(
                          "<entradaMedicamentos>"
                         + "<medicamentoEntrada>"
                          + "<classeTerapeutica> " + item.t0051_tipo_subs + " +</classeTerapeutica>"
                          + "<registroMSMedicamento>1888888888888</registroMSMedicamento>"
                          + "<numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>"
                          + "<quantidadeMedicamento>12</quantidadeMedicamento>"
                           + "<unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>"
                          + "</medicamentoEntrada>"
                           + "</entradaMedicamentos>"
                          );
                        }


                        // encerra o elemento raiz
                        writer.WriteEndElement();
                        //Escreve o XML para o arquivo e fecha o objeto escritor
                        writer.Close();



                    }
  • 1

    Instead of using the writer.WriteRaw you put it in a string... It would already be in memory, but I don’t know if that’s what you want... Better defines what you need.

  • I need that instead of recording on the record, record in memory, it can be in a string yes, how would do that ?

4 answers

4

Can I give you a hint, don’t mount the XML in your hand. You can and should define a contract as the below.:

[DataContract(Name = "mensagemSNGPCInventario", Namespace = "urn:sngpc-schema")]
public class NotaFiscal
{
    [DataMember(Name = "cabecalho", Order = 1)]
    public Cabecalho Cabecalho { get; set; } = new Cabecalho();
    [DataMember(Name = "corpo", Order = 2)]
    public Corpo Corpo { get; set; } = new Corpo();
}

[DataContract(Name = "cabecalho", Namespace = "urn:sngpc-schema")]
public class Cabecalho
{
    [DataMember(Name = "cnpjEmissor", Order = 1)]
    public string CnpjEmissor { get; set; } = "12935236000107";
    [DataMember(Name = "cpfTransmissor", Order = 2)]
    public string CpfTransmissor { get; set; } = "01472346971";
    [DataMember(Name = "data", Order = 3)]
    public DateTime Data { get; set; } = new DateTime(2006, 1, 1);
}

[DataContract(Name = "corpo", Namespace = "urn:sngpc-schema")]
public class Corpo
{
    [DataMember(Name = "medicamentos", Order = 1)]
    public Medicamentos Medicamentos { get; set; } = new Medicamentos();
}

[CollectionDataContract(Name = "medicamentos", Namespace = "urn:sngpc-schema")]
public class Medicamentos : List<MedicamentoWrapper>
{

}

[DataContract(Name = "entradaMedicamentos", Namespace = "urn:sngpc-schema")]
public class MedicamentoWrapper
{
    [DataMember(Name = "medicamentoEntrada", Order = 1)]
    public Medicamento Medicamento { get; set; } = new Medicamento();
}

[DataContract(Name = "medicamentoEntrada", Namespace = "urn:sngpc-schema")]
public class Medicamento
{
    [DataMember(Name = "classeTerapeutica", Order = 1)]
    public string ClasseTerapeutica { get; set; }
    [DataMember(Name = "registroMSMedicamento", Order = 2)]
    public string RegistroMSMedicamento { get; set; } = "1888888888888";
    [DataMember(Name = "numeroLoteMedicamento", Order = 3)]
    public string NumeroLoteMedicamento { get; set; } = "AACCBB";
    [DataMember(Name = "quantidadeMedicamento", Order = 4)]
    public int QuantidadeMedicamento { get; set; } = 12;
    [DataMember(Name = "unidadeMedidaMedicamento", Order = 5)]
    public int UnidadeMedidaMedicamento { get; set; } = 1;
}

Then you can execute the following code.:

var notaFiscal = new NotaFiscal();
var medicamentos = notaFiscal.Corpo.Medicamentos;
for (var indice = 0; indice < 10; indice++)
{
    var medicamento = new MedicamentoWrapper();
    medicamento.Medicamento.ClasseTerapeutica = Guid.NewGuid().ToString();
    notaFiscal.Medicamentos.Add(medicamento);
}

var serializer = new DataContractSerializer(typeof(NotaFiscal));
var settings = new XmlWriterSettings
{
    Encoding = Encoding.GetEncoding("ISO-8859-1"),
    NewLineHandling = NewLineHandling.Entitize,
    NewLineChars = Environment.NewLine,
    Indent = true
};
using (var stream = new MemoryStream())
{
    using (var writer = XmlDictionaryWriter.Create(stream, settings))
    {
        serializer.WriteObject(writer, notaFiscal);
    }

    using (var reader = new StreamReader(stream))
    {
        stream.Position = 0;
        var xml = reader.ReadToEnd();
    }
}

This will generate the following XML.:

<?xml version="1.0" encoding="utf-16"?>
<mensagemSNGPCInventario xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:sngpc-schema">
  <cabecalho>
    <cnpjEmissor>12935236000107</cnpjEmissor>
    <cpfTransmissor>01472346971</cpfTransmissor>
    <data>2006-01-01T00:00:00</data>
  </cabecalho>
  <corpo>
    <medicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>a4eea288-e54e-413c-8a3a-290ac57c21fb</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>0550972b-de44-441e-ba22-b25be0d16e3f</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>183c17ec-2605-40fa-afc9-67bb1437e19d</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>c581eab3-39ec-44b9-a1d9-24d9f11c7ac9</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>90ee2e2b-ecae-4d0b-9637-3c1e638566df</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>724ef7e2-4f0c-464a-9687-f108cbe68410</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>83a6f068-b7d1-489e-a613-b8742e9161dd</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>19501ba5-2f8d-4959-b0b8-85ea0dea666f</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>28b1e29f-f947-4a4d-a654-d28687cbddc3</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
      <entradaMedicamentos>
        <medicamentoEntrada>
          <classeTerapeutica>110aebac-f3a1-421b-8402-dc6830bedeeb</classeTerapeutica>
          <registroMSMedicamento>1888888888888</registroMSMedicamento>
          <numeroLoteMedicamento>AACCBB</numeroLoteMedicamento>
          <quantidadeMedicamento>12</quantidadeMedicamento>
          <unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
        </medicamentoEntrada>
      </entradaMedicamentos>
    </medicamentos>
  </corpo>    
</mensagemSNGPCInventario>

If you want to write this XML in a file (as you are doing today), use the File.WriteAllText

File.WriteAllText(filePath, xml);

If you just want to store the XML in memory, just modify the Writer being used.:

var binary = default(byte[]);
var serializer = new DataContractSerializer(typeof(NotaFiscal));
using (var stream = new MemoryStream())
{
    using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream))
    {
        serializer.WriteObject(writer, notaFiscal);                    
        stream.Position = 0;
        stream.Flush();
        binary = stream.ToArray();
    }
}
  • q need to import to use Datacontract and Datamember, imported using System.xml.Linq; using System.Xml; using System.Runtime.Serialization;, but did not give

  • @alessandremartins you have to add a reference to System.Runtime.Serialization 4.0.0.0 in your project.

  • Tobias, implemented here, perfect!!! , just a detail, the <entered> tag has q have in all repetitions, help me there, where I change.

  • @alessandremartins as a rule, your contracts should reflect the structure of XML, in this case I have already edited the contracts and the examples.

  • look, it all worked out, but there’s still one detail, the two initial nodes have to look like this: <?xml version="1.0" encoding="iso-8859-1" ? > <messaging SNGPC xmlns="urn:sngpc-schema">, boy... complex and so, but I’ll learn to deal with it.

  • Look, the first line informs the Encode to be used, if you are waiting for ISO-8859-1, then you should perform Encoding using Encoding.GetEnconding("ISO-8859-1") and not the Encoding.UTF8 as you reported earlier, remembering that both are different. The xmlns:i should not affect the life of those who receive XML, so do not worry about it.

Show 1 more comment

3

Saving in a string

Instead of passing a path by instantiating a XmlTextWriter, pass an instance of StringBuilder.

var strBuilder = new StringBuilder(); 
var writer = new XmlTextWriter(strBuilder , null);

The variable strBuilder will contain the generated XML.

Using MemoryStream

Another option is to save the stream in one MemoryStream. Use an instance of XmlWriterSettings to force the encoding.

var settings = new XmlWriterSettings();
settings.Enconding = Encoding.UTF8;

var stream = new MemoryStream();     
var writer = XmlWriter.Create(strBuilder , settings );

And to get the stream value in a string (Obs.: don’t forget to call Dispose in the XmlWritter)

string conteudo = System.Text.Encoding.UTF8.GetString(myStream.GetBuffer());
  • This method does not consider the encoding selected, in Xmlwritersettings.Encoding even set as UTF-8 it generates UTF-16, would you know how to solve this? I give Replace I don’t know if it’s the best way.

  • But for that enconding if it will stay in memory?

  • jbueno, I did as you said, but gave a conflict in that line: var Writer = new Xmltextwriter(strBuilder, null);. the conflict is : argument1: cannot Convert from system.stringbuilder to System.IO.Strean

  • What a conflict, man?

  • The need for encoding is why I use that xml to be transmitted and the receiver needs it to be with UTF-8

  • @Edenilsonbila So you need to set the enconding when broadcasting, no?

  • @jbueno This does not work well. It is better to use MemoryStream (which effectively writes in memory) and then convert to String if applicable.

  • But why doesn’t it work well? I mean, that’s super normal. Saves the flow in a string and sends it when you need it.

  • The author of the question has already said: coding is not defined. You can change your answer to parameterize serialization and ensure UTF-8 and yet there will be trouble with writing the metatag of namespace. I’ll see if I can find a code here to also give an answer.

  • @Gypsy omorrisonmendez I wait then. I gave the option to MemoryStream, but I’m not sure that’s how it is.

  • Yes, but also define an object XmlWriterSettings to force encoding.

Show 6 more comments

3

Writing raw XML (as you did) is bad practice. There is no mention of the DTD, no encoding statement, no definition of namespaces which, however not the case, generates an XML outside the formatting pattern defined by W3C.

The . NET has some classes to format this properly. The reply from @Tobiasmesquita is quite adequate, but I’ll give you another answer with some more settings.

Use the same domain of classes that will be serialized in XML, with their respective [DataContract] defined.

Implement the following extension:

public static class XmlDocumentExtensions
{
    public static XmlDocument ToXmlDocument(this object input, string encoding = "UTF-8", bool removeNamespaces = false, String xmlRoot = "", String xmlNamespace = "")
    {
        XmlSerializer ser;

        XmlDocument xd = null;

        // Se o XML for muito grande, use MemoryTributary. 
        // Veja mais sobre ele em https://github.com/tibel/Weakly
        // using (var memStm = new MemoryTributary())
        using (var memStm = new MemoryStream())
        {
            if (removeNamespaces)
            {
                ser = new XmlSerializer(input.GetType());
                XmlWriterSettings xws = new XmlWriterSettings();
                // xws.OmitXmlDeclaration = true;
                xws.Encoding = Encoding.UTF8;
                var xtw = XmlTextWriter.Create(memStm, xws);
                var namespaces = (XmlSerializerNamespaces)input.GetType().GetProperty("Namespaces").GetValue(input, null);
                ser.Serialize(xtw, input, namespaces);
            }
            else
            {
                ser = new XmlSerializer(input.GetType());
                ser.Serialize(memStm, input);
            }

            memStm.Position = 0;

            // O XML aqui está em memStr.
            // Abaixo coloco um código que demonstra como esse Stream pode ser lido
            // e devolvido na forma de um XmlDocument, por exemplo.
            // Este XmlDocument pode ser salvo em arquivo (usando FileStream)
            // ou devolvido numa aplicação Web usando return XmlContent.

            XmlReaderSettings settings = new XmlReaderSettings { CheckCharacters = false };
            settings.IgnoreWhitespace = true;
            // Se ficar muito lento, habilite a linha abaixo. 
            // Não é recomendável no início. Apenas use se seu XML está 100%.
            //settings.DtdProcessing = DtdProcessing.Prohibit;

            using (var xtr = XmlReader.Create(memStm, settings))
            {
                xd = new XmlDocument();
                xd.XmlResolver = null;
                xd.Load(xtr);
            }

            if (xd.FirstChild.NodeType == XmlNodeType.XmlDeclaration)
            {
                XmlDeclaration xmlDeclaration = (XmlDeclaration)xd.FirstChild;
                xmlDeclaration.Encoding = encoding;
            }

            return xd;
        }
    }
}

Use:

var notaFiscal = new NotaFiscal();
// Defina todas as informações de NotaFiscal aqui.
var xmlDocument = notaFiscal.ToXmlDocument();

0

Use Stringbuilder to log in, I use this method and it works perfectly:

 StringBuilder xmlFormado = new StringBuilder();

            //Estacia o Objeto XML
            XmlWriter arqXml = XmlWriter.Create(xmlFormado, null);

             //SEU XML AQUI EX:
             arqXml.WriteStartDocument(); //Inicio do XMl
             arqXml.WriteEndDocument(); //Fim do arquivo XMl

             //libera o XmlWriter
            arqXml.Flush();
            //fechar o XmlWriter
            arqXml.Close();
            //Termina aqui

          //Os replace troca o utf-16 para 8 e limpa uma sujeira que fica no final do arquivo.
          var xmlString = xmlFormado.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "").Replace(@"\", "");

Browser other questions tagged

You are not signed in. Login or sign up in order to post.