none
Como faço para ler dados de string XML? RRS feed

  • Pergunta

  • Olá. Preciso carregar os itens de um string XML em um ListView. Essa string pego da Web.

    Fiz o seguinte código utilizando XmlDocument:

    HttpClient http = new System.Net.Http.HttpClient();
    HttpResponseMessage response = await http.GetAsync("url");
    string str = await response.Content.ReadAsStringAsync();
                
    XmlDocument xml = new XmlDocument();
    xml.LoadXml(str);
    
    XmlNodeList nodes = xml.DocumentElement.ChildNodes;

    Aparentemente era para estar tudo certo, porém quando tento obter os valores, eles estão em uma ordem diferente, e só consigo obter eles com número ímpares. Por exemplo:

    nodes.Item(1).ChildNodes.Item(1).InnerText; //pega o primeiro item
    nodes.Item(3).ChildNodes.Item(1).InnerText; //pega o segundo item

    Como está meu XML:

    <?xml version="1.0"?>
    <posts>
      <item>
        <title>titulo1</title>
        <image>unavailable</image>
        <link>link1</link>
      </item>
      <item>
        <title>title2</title>
        <image>unavailable</image>
        <link>link2</link>
      </item>
    </posts>

    Como faço pra resolver? Obrigado.

    quinta-feira, 23 de junho de 2016 21:02

Respostas

  • Boa noite,

    Uma sugestão seria você criar uma classe de acordo com o "xml" e carregar o objeto de acordo com o xml. Segue um exemplo:
    Classe:

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class MyClassXML
    {
    
        private postsItem[] itemField;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("item")]
        public postsItem[] item
        {
            get
            {
                return this.itemField;
            }
            set
            {
                this.itemField = value;
            }
        }
    }
    
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class postsItem
    {
    
        private string titleField;
    
        private string imageField;
    
        private string linkField;
    
        /// <remarks/>
        public string title
        {
            get
            {
                return this.titleField;
            }
            set
            {
                this.titleField = value;
            }
        }
    
        /// <remarks/>
        public string image
        {
            get
            {
                return this.imageField;
            }
            set
            {
                this.imageField = value;
            }
        }
    
        /// <remarks/>
        public string link
        {
            get
            {
                return this.linkField;
            }
            set
            {
                this.linkField = value;
            }
        }
    }

    Método para carregar o xml:

    public MyClassXML FromXmlString(string xmlString)
    {
        var reader = new StringReader(xmlString);
        var serializer = new XmlSerializer(typeof(MyClassXML));
        var instance = (MyClassXML)serializer.Deserialize(reader);
    
        return instance;
    }

    "Chamar" o método:

    var sXml = "<?xml version=\"1.0\"?><posts><item><title>titulo1</title><image>unavailable</image><link>link1</link></item><item><title>title2</title><image>unavailable</image><link>link2</link></item></posts>";
    
    MyClassXML xml = FromXmlString(sXml); 

    Desse forma fica fácil você acessar os atributos do objeto.

    Espero ter ajudado.

    Att,


    Se a resposta contribuiu com seu aprendizado por favor marque como util, se solucionou seu problema marque como resposta.

    • Sugerido como Resposta Silvaney sexta-feira, 24 de junho de 2016 12:12
    • Marcado como Resposta Thales F Quintas sexta-feira, 24 de junho de 2016 12:33
    • Não Marcado como Resposta Free4k sábado, 25 de junho de 2016 00:02
    • Marcado como Resposta Free4k domingo, 26 de junho de 2016 04:23
    quinta-feira, 23 de junho de 2016 23:40
  • Boa noite,

    Segue alguns exemplos de como acessar a lista:
    posts  xml_posts = FromXmlString(sXml);
    var title = xml_posts.item[0].title; //Acessar a primeira posição
    title = xml_posts.item[1].title; //Acessar a segunta posição
    
    var query = xml_posts.item.Where(x => x.title.Equals("title2")).FirstOrDefault();//Obter pelo titulo
    title = query.title;
    
    //Percorrer a lista
    foreach (var item in xml_posts.item)
    {
        Console.WriteLine(item.title + "-" + item.link);
    }
    Marque como resposta por favor.

    Att,

    Se a resposta contribuiu com seu aprendizado por favor marque como util, se solucionou seu problema marque como resposta.

    • Marcado como Resposta Free4k domingo, 26 de junho de 2016 04:23
    sábado, 25 de junho de 2016 23:31
  • Boa tarde,

    Tente renomear a classe e deixar com o mesmo nome criado ao seguir o procedimento de "colar especial".
    Ou seja ao invés de "Posts" renomeie para "posts".

    Att,


    Se a resposta contribuiu com seu aprendizado por favor marque como util, se solucionou seu problema marque como resposta.

    • Marcado como Resposta Free4k segunda-feira, 27 de junho de 2016 00:59
    domingo, 26 de junho de 2016 21:10

Todas as Respostas

  • Boa noite,

    Uma sugestão seria você criar uma classe de acordo com o "xml" e carregar o objeto de acordo com o xml. Segue um exemplo:
    Classe:

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class MyClassXML
    {
    
        private postsItem[] itemField;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("item")]
        public postsItem[] item
        {
            get
            {
                return this.itemField;
            }
            set
            {
                this.itemField = value;
            }
        }
    }
    
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class postsItem
    {
    
        private string titleField;
    
        private string imageField;
    
        private string linkField;
    
        /// <remarks/>
        public string title
        {
            get
            {
                return this.titleField;
            }
            set
            {
                this.titleField = value;
            }
        }
    
        /// <remarks/>
        public string image
        {
            get
            {
                return this.imageField;
            }
            set
            {
                this.imageField = value;
            }
        }
    
        /// <remarks/>
        public string link
        {
            get
            {
                return this.linkField;
            }
            set
            {
                this.linkField = value;
            }
        }
    }

    Método para carregar o xml:

    public MyClassXML FromXmlString(string xmlString)
    {
        var reader = new StringReader(xmlString);
        var serializer = new XmlSerializer(typeof(MyClassXML));
        var instance = (MyClassXML)serializer.Deserialize(reader);
    
        return instance;
    }

    "Chamar" o método:

    var sXml = "<?xml version=\"1.0\"?><posts><item><title>titulo1</title><image>unavailable</image><link>link1</link></item><item><title>title2</title><image>unavailable</image><link>link2</link></item></posts>";
    
    MyClassXML xml = FromXmlString(sXml); 

    Desse forma fica fácil você acessar os atributos do objeto.

    Espero ter ajudado.

    Att,


    Se a resposta contribuiu com seu aprendizado por favor marque como util, se solucionou seu problema marque como resposta.

    • Sugerido como Resposta Silvaney sexta-feira, 24 de junho de 2016 12:12
    • Marcado como Resposta Thales F Quintas sexta-feira, 24 de junho de 2016 12:33
    • Não Marcado como Resposta Free4k sábado, 25 de junho de 2016 00:02
    • Marcado como Resposta Free4k domingo, 26 de junho de 2016 04:23
    quinta-feira, 23 de junho de 2016 23:40
  • Criei um arquivo de classe e inseri o código.  Apareceram os seguintes erros:

    Severity	Code	Description	Project	File	Line	Suppression State
    Error	CS0234	The type or namespace name 'SerializableAttributeAttribute' does not exist in the namespace 'System' (are you missing an assembly reference?)	ApontaDownloads	C:\Users\user\OneDrive\#Developer\Windows Phone\ApontaDownloads\ApontaDownloads\MyClassXML.cs	2	Active
    Error	CS0234	The type or namespace name 'SerializableAttribute' does not exist in the namespace 'System' (are you missing an assembly reference?)	ApontaDownloads	C:\Users\user\OneDrive\#Developer\Windows Phone\ApontaDownloads\ApontaDownloads\MyClassXML.cs	2	Active
    Error	CS0234	The type or namespace name 'DesignerCategoryAttributeAttribute' does not exist in the namespace 'System.ComponentModel' (are you missing an assembly reference?)	ApontaDownloads	C:\Users\user\OneDrive\#Developer\Windows Phone\ApontaDownloads\ApontaDownloads\MyClassXML.cs	3	Active
    Error	CS0234	The type or namespace name 'DesignerCategoryAttribute' does not exist in the namespace 'System.ComponentModel' (are you missing an assembly reference?)	ApontaDownloads	C:\Users\user\OneDrive\#Developer\Windows Phone\ApontaDownloads\ApontaDownloads\MyClassXML.cs	3	Active
    Error	CS0234	The type or namespace name 'SerializableAttributeAttribute' does not exist in the namespace 'System' (are you missing an assembly reference?)	ApontaDownloads	C:\Users\user\OneDrive\#Developer\Windows Phone\ApontaDownloads\ApontaDownloads\MyClassXML.cs	27	Active
    Error	CS0234	The type or namespace name 'SerializableAttribute' does not exist in the namespace 'System' (are you missing an assembly reference?)	ApontaDownloads	C:\Users\user\OneDrive\#Developer\Windows Phone\ApontaDownloads\ApontaDownloads\MyClassXML.cs	27	Active
    Error	CS0234	The type or namespace name 'DesignerCategoryAttributeAttribute' does not exist in the namespace 'System.ComponentModel' (are you missing an assembly reference?)	ApontaDownloads	C:\Users\user\OneDrive\#Developer\Windows Phone\ApontaDownloads\ApontaDownloads\MyClassXML.cs	28	Active
    Error	CS0234	The type or namespace name 'DesignerCategoryAttribute' does not exist in the namespace 'System.ComponentModel' (are you missing an assembly reference?)	ApontaDownloads	C:\Users\user\OneDrive\#Developer\Windows Phone\ApontaDownloads\ApontaDownloads\MyClassXML.cs	28	Active
    Warning		APPX4001: Build property AppxBundlePlatforms is not explicitly set and is calculated based on currently building architecture. Use 'Create App Package' wizard or edit project file to set it.	ApontaDownloads			
    

    sábado, 25 de junho de 2016 00:01
  • Boa noite,

    Para gerar a classe, segue o seguinte procedimento:
     - Copie o xml (string) 
     - Crie uma classe
     - Remova "class nomeDaClasse{}", deixando só o namespace { }
     - No Visual Studio, clique em Edit -> Paste Special -> Paste XML as Classes

    Pronto, será criado a classe, agora você pode renomear a classe ou instanciar com o nome criado.

    Att,

     

    Se a resposta contribuiu com seu aprendizado por favor marque como util, se solucionou seu problema marque como resposta.

    sábado, 25 de junho de 2016 03:33
  • Muito interessante. Não sabia disso.

    E como faço para definir o index que desejo obter?

    Posts xml_posts = FromXmlString(str);
    myCells.Add(new myCell() { Title = xml_posts.item.title, Content = xml_posts.item.title });
    this.DataContext = myCells;

    sábado, 25 de junho de 2016 15:51
  • Boa noite,

    Segue alguns exemplos de como acessar a lista:
    posts  xml_posts = FromXmlString(sXml);
    var title = xml_posts.item[0].title; //Acessar a primeira posição
    title = xml_posts.item[1].title; //Acessar a segunta posição
    
    var query = xml_posts.item.Where(x => x.title.Equals("title2")).FirstOrDefault();//Obter pelo titulo
    title = query.title;
    
    //Percorrer a lista
    foreach (var item in xml_posts.item)
    {
        Console.WriteLine(item.title + "-" + item.link);
    }
    Marque como resposta por favor.

    Att,

    Se a resposta contribuiu com seu aprendizado por favor marque como util, se solucionou seu problema marque como resposta.

    • Marcado como Resposta Free4k domingo, 26 de junho de 2016 04:23
    sábado, 25 de junho de 2016 23:31
  • Sempre que uso a class ocorre um erro inesperado (em execução).

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace AppName
    {
    
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
        public partial class Posts
        {
    
            private postsItem[] itemField;
    
            /// <remarks/>
            [System.Xml.Serialization.XmlElementAttribute("item")]
            public postsItem[] item
            {
                get
                {
                    return this.itemField;
                }
                set
                {
                    this.itemField = value;
                }
            }
        }
    
        /// <remarks/>
        //[System.SerializableAttribute()]
        //[System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
        public partial class postsItem
        {
    
            private string titleField;
    
            private string imageField;
    
            private string linkField;
    
            /// <remarks/>
            public string title
            {
                get
                {
                    return this.titleField;
                }
                set
                {
                    this.titleField = value;
                }
            }
    
            /// <remarks/>
            public string image
            {
                get
                {
                    return this.imageField;
                }
                set
                {
                    this.imageField = value;
                }
            }
    
            /// <remarks/>
            public string link
            {
                get
                {
                    return this.linkField;
                }
                set
                {
                    this.linkField = value;
                }
            }
        }
    
    }
    

    Posts xml_posts = FromXmlString(str);
    Windows.UI.Popups.MessageDialog msgbox = new Windows.UI.Popups.MessageDialog(xml_posts.item[0].title.ToString());
    await msgbox.ShowAsync();

    domingo, 26 de junho de 2016 15:07
  • Boa tarde,

    Tente renomear a classe e deixar com o mesmo nome criado ao seguir o procedimento de "colar especial".
    Ou seja ao invés de "Posts" renomeie para "posts".

    Att,


    Se a resposta contribuiu com seu aprendizado por favor marque como util, se solucionou seu problema marque como resposta.

    • Marcado como Resposta Free4k segunda-feira, 27 de junho de 2016 00:59
    domingo, 26 de junho de 2016 21:10
  • Era isso mesmo. Muito obrigado!
    segunda-feira, 27 de junho de 2016 00:59