Jump to content

[C#] Como ler um ficheiro xml usando C# - bibliotecas (?)


saramgsilva

Recommended Posts

Boas,

bem pessoal, estou com uma dúvida... É o seguinte eu tenho um esquema em Xml e tenho um ficheiro Xml de exemplo, em que o meu Xml Schema valida bem o xml!

Agora quero, usando C#, ler o ficheiro XML actual que tenho e escrever um novo ficheiro xml (primeiro queria ignorar a validação e só depois me preocupar com isso!não sei se estou a ir no melhor caminho....)

a minha questão é:

Qual biblioteca usar, XMLReader() ou XmlTextReader() e XMLWrite() ou XMLTextWrite()?

é assim eu vou querer guardar a informação que leio nos meus objectos e pegar nos objectos e escrever os objectos no xml!

Um exemplo que já tenho é este, mas não está a fazer bem o que quero:


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.IO;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create the XmlSchemaSet class.
            XmlSchemaSet sc = new XmlSchemaSet();

            // Add the schema to the collection.
            sc.Add("urn:bookstore-schema", "C:\\Documents and Settings\\SMSilva\\Desktop\\Exemplo Teste\\ProjectoXML\\ConsoleApplicationXML1\\books.xsd");

            // Set the validation settings.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = sc;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

            // Create the XmlReader object.
            XmlReader reader = XmlReader.Create("C:\\Documents and Settings\\SMSilva\\Desktop\\Exemplo Teste\\ProjectoXML\\ConsoleApplicationXML1\\booksSchemaFail.xml", settings);


            while (reader.Read())
            {   

                switch (reader.NodeType)
                {
                    case XmlNodeType.Element: // The node is an element.
                        Console.Write("<" + reader.Name);

                        while (reader.MoveToNextAttribute()) // Read the attributes.
                            Console.Write(" " + reader.Name + "='" + reader.Value + "'");
                        Console.WriteLine(">");

                        break;
                    case XmlNodeType.Text: //Display the text in each element.
                        Console.WriteLine("\t"+reader.Value);

                        break;
                    case XmlNodeType.EndElement: //Display the end of the element.
                        Console.Write("</" + reader.Name);
                        Console.WriteLine(">");

                        break;
                }
            }


        }

        // Display any validation errors.
        private static void ValidationCallBack(object sender, ValidationEventArgs e)
        {
             Console.WriteLine("Validation Error: {0}\n", e.Message);
        }
    }
}

bom trabalho

tofas

p.s: no exemplo tenho a parte de verificar segundo o meu esquema, mas estou a ignorar um pouco isso...estou mais concentrada em como apanhar os dados!

Link to comment
Share on other sites

boas,

imagina que tenho as classes:


    class ClassEmpresa
    {
        string _nome;
        int _contribuinte;
        Departamento _dep;
        Empregado _emp;
    }
    class Departamento
    {
        string _name;
        string _departamentoID;
    }

    class Empregado
    {
        string _nome;
        string _funcao;
        Departamento _depEmp;
    }

e o xml

<?xml version="1.0" encoding="utf-8" ?>
<empresa
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="Tofas.xsd"
        nome="SARASILVA, Lda"
        contribuinte="123">
  <departamento name="Human Resources" departamentoID="depart_RH"/>
  <departamento name="Development" departamentoID="depart_desenvolvimento"/>
  <departamento name="Financeira" departamentoID="depart_financeiro"/>

  <empregado departamento="depart_RH">
    <nome>Sara Joana</nome>
    <funcao>Psicologo</funcao>
  </empregado>
  <empregado departamento="depart_desenvolvimento">
    <nome>Maunuel Ferro</nome>
    <funcao>Analista</funcao>
  </empregado>
  <empregado departamento="depart_desenvolvimento">
    <nome>Maria Alves</nome>
    <funcao>Programador</funcao>
  </empregado>
  <empregado departamento="depart_financeiro">
    <nome>Alberto Fernando</nome>
    <funcao>TOC</funcao>
  </empregado>

</empresa>

e depois eu quero guarda a informação

Empresa empresa = new Empresa();

empresa.nome = "SARASILVA, Lda";
empresa.contribuinte="123";                              Mas estes valores sou eu que vou ler e guardar com as bibliotecas do XML
empresa.depart.name="...";
empresa.depart.departamentoID="..."

eu tenho saber destiguir o root, os nodes, os elementos e os atributos dentro dos elementos e dentro.... Humm não sei se me fiz entender...

Bem vou tentar implementar este exemplo que tentei explicar de uma forma se calhar pouco clara! a ver se consigo o que quero...

Então mas eu estou a ir no bom caminho ao usar o XMLReader??? não deveria usar o XMLTextReader?

:wallbash:

bom trabalho!

tofas

Link to comment
Share on other sites

boas,

já implementei as classes e já estou a trabalhar no MAIN, mas tenho alterar as coisas de modo a guardar a informação, ora vejamos o código:


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

namespace Project1
{
    static class Utils
    {


        static public string CollectToString(ICollection collection)
        {
            string text = "";

            foreach (object obj in collection)
            {
                text = text + "\t" + obj.ToString();// +"\n";
            }

            return text;

        }
    }

    class Empresa
    {
        //fields
        private string _nome;
        private int _contribuinte;
        private List<Departamento> _dep;
        private List<Empregado> _emp;

        //constructor
        public Empresa()
        {
            _nome = "unkown";
            _contribuinte = 0;
            _dep = new List<Departamento>();
            _emp = new List<Empregado>();

        }

        //properties
        public string Nome
        {
            get { return _nome; }
            set { _nome = value; }
        }
        public int Contribuinte
        {
            get { return _contribuinte; }
            set { _contribuinte = value; }
        }
        internal List<Departamento> Dep
        {
            get { return _dep; }
        }
        internal List<Empregado> Emp
        {
            get { return _emp; }

        }

        //methods
        public Departamento CreateDepartamento(string name, string departamentoID)
        {
            Departamento dep = new Departamento(name, departamentoID);
            _dep.Add(dep);

            return dep;
        }

        public Empregado CreateEmperagado(string name, string funcao)
        {
            Empregado emp = new Empregado(name, funcao);
            _emp.Add(emp);
            return emp;
        }

        public override string ToString()
        {
            return "Empresa: <nome> " + _nome + " <contribuinte> " + _contribuinte + "; <departamentos> " + Utils.CollectToString(_dep) + " <empregados> " + Utils.CollectToString(_emp);
        }
    }

    class Departamento
    {
        //fields
        string _name;
        string _departamentoID;

        //constructor
        internal Departamento()
        {
            _name = "unkwon";
            _departamentoID = "unkwon";
        }
        internal Departamento(string name, string departamentoID)
        {
            _name = name;
            _departamentoID = departamentoID;
        }

        //properties
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        public string DepartamentoID
        {
            get { return _departamentoID; }
            set { _departamentoID = value; }
        }

        //methods
        public override string ToString()
        {
            return " Departamento: <name>" + _name + " <id> " + _departamentoID;
        }
    }

    class Empregado
    {
        //fields
        string _nome;
        string _funcao;
        Departamento _depEmp;

        //constructor
        internal Empregado()
        {
            _nome = "unknown";
            _funcao = "unkown";
            _depEmp = new Departamento();
        }
        internal Empregado(string nome, string funcao)
        {
            _nome = nome;
            _funcao = funcao;
        }

        //properties
        public string Nome
        {
            get { return _nome; }
            set { _nome = value; }
        }
        public string Funcao
        {
            get { return _funcao; }
            set { _funcao = value; }
        }
        internal Departamento DepEmp
        {
            get { return _depEmp; }
            set { _depEmp = value; }
        }

        //methods
        public void AddDepart(Departamento dep)
        {
            _depEmp = dep;
        }

        public override string ToString()
        {
            return " Empregado: <name>" + _nome + " <funcao> " + _funcao + " Departamento " + _depEmp.ToString();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Create the XmlSchemaSet class.
            XmlSchemaSet sc = new XmlSchemaSet();

            // Add the schema to the collection.
            sc.Add("urn:bookstore-schema", "C:\\Documents and Settings\\SMSilva\\Desktop\\Exemplo Teste\\projecto teste\\Project1\\Project1\\Tofas.xsd");

            // Set the validation settings.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = sc;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

            // Create the XmlReader object.
            XmlReader reader = XmlReader.Create("C:\\Documents and Settings\\SMSilva\\Desktop\\Exemplo Teste\\projecto teste\\Project1\\Project1\\tofas.xml", settings);


            while (reader.Read())
            {

                // attributes
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element: // The node is an element.
                        Console.Write("<" + reader.Name);

                        while (reader.MoveToNextAttribute()) // Read the attributes.
                            Console.Write(" " + reader.Name + "='" + reader.Value + "'");
                        Console.WriteLine(">");

                        break;
                    case XmlNodeType.Text: //Display the text in each element.
                        Console.WriteLine("\t" + reader.Value);

                        break;
                    case XmlNodeType.EndElement: //Display the end of the element.
                        Console.Write("</" + reader.Name);
                        Console.WriteLine(">");

                        break;
                }
            }


        }

        // Display any validation errors.
        private static void ValidationCallBack(object sender, ValidationEventArgs e)
        {
            Console.WriteLine("Validation Error: {0}\n", e.Message);
        }
    }
}


dentro do   

while (reader.Read())

  tenho que separar as coisas, de modo a guardar a informação na classe Empresa ( onde crio os departamentos e empregados!)

eu neste momento estou so a escrever na consola o que leio e diferencio segundo o tipo de nó... :dontgetit:

Eu tenho que ter atenção aos atributos pois quando leio

<empregado departamento="depart_financeiro">

tenho que criar um novo empregado e adicionar-te o departamento que lhe corresponde!

eu estou com dificuldades ai!  :wallbash:

deixo o meu xml e xml schemas são:

XML


<?xml version="1.0" encoding="utf-8" ?>
<empresa
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="Tofas.xsd"
        nome="SARASILVA, Lda"
        contribuinte="123">
  <departamento name="Human Resources" departamentoID="depart_RH"/>
  <departamento name="Development" departamentoID="depart_desenvolvimento"/>
  <departamento name="Financeira" departamentoID="depart_financeiro"/>

  <empregado departamento="depart_RH">
    <nome>Sara Joana</nome>
    <funcao>Psicologo</funcao>
  </empregado>
  <empregado departamento="depart_desenvolvimento">
    <nome>Maunuel Ferro</nome>
    <funcao>Analista</funcao>
  </empregado>
  <empregado departamento="depart_desenvolvimento">
    <nome>Maria Alves</nome>
    <funcao>Programador</funcao>
  </empregado>
  <empregado departamento="depart_financeiro">
    <nome>Alberto Fernando</nome>
    <funcao>TOC</funcao>
  </empregado>

</empresa>

o XSD


<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           elementFormDefault="qualified" attributeFormDefault="unqualified">
  <!-- Company -->
  <xs:element name="empresa">
    <xs:complexType>
      <xs:sequence>
        <!-- departamento-->
        <xs:element name="departamento" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attribute name="name" type="xs:string" />
            <xs:attribute name="departamentoID" type="xs:string" />
          </xs:complexType>
        </xs:element>
        <!-- empregado -->
        <xs:element name="empregado" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="nome" type="xs:string" />
              <xs:element name="funcao" type="xs:string" />
            </xs:sequence>
            <xs:attribute name="departamento" type="xs:string" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute name="nome" type="xs:string" />
      <xs:attribute name="contribuinte" type="xs:integer" />
    </xs:complexType>
    <!-- KeydepartamentoByID -->
    <xs:key name="DepartamentoByID">
      <xs:selector xpath="departamento" />
      <xs:field xpath="@departamentoID" />
    </xs:key>
    <!-- RefempregadoTodepartamento -->
    <xs:keyref name="RefEmpregado" refer="DepartamentoByID">
      <xs:selector xpath="empregado" />
      <xs:field xpath="@departamento" />
    </xs:keyref>
  </xs:element>
</xs:schema>

vou continuar a pensar na solução....se alguém poder ajudar, agradeço!

bom trabalho

tofas

Link to comment
Share on other sites

Então mas eu estou a ir no bom caminho ao usar o XMLReader??? não deveria usar o XMLTextReader?

:wallbash:

Sim claro. Na própria API diz para se usar o XmlReader com o método Create. XmlReader é a classe abstracta em que o XmlTextReader herda, mas há mais outros readers. No Create é intanciado uma dessas classes, poderá ser o XmlTextReader ou não, mas do nosso ponto de vista, isso é indiferente e deve-se sempre trabalhar com a abstracta.

dentro do   

while (reader.Read())

  tenho que separar as coisas, de modo a guardar a informação na classe Empresa ( onde crio os departamentos e empregados!)

eu neste momento estou so a escrever na consola o que leio e diferencio segundo o tipo de nó... :dontgetit:

Eu tenho que ter atenção aos atributos pois quando leio

<empregado departamento="depart_financeiro">

tenho que criar um novo empregado e adicionar-te o departamento que lhe corresponde!

eu estou com dificuldades ai!  :wallbash:

É assim, não tenho muito experiência a usar o XmlReader, normalmente quando uso Xml é porque foi gerado por nós internamente e não faço qualquer validação, nesses casos simplesmente faço um XmlDocument e faço load ao ficheiro xml. Depois trabalho sobre o documeto Xml com o xpath.

Neste caso, isto está fora de questão porque queres que haja validação.

Aconselhava-te a fazeres uma função para processar cada tipo de nodo, ou seja, uma função para processar um nodo de xml de departamento e outra funcao para processar um nodo de xml de empregado.

Estas funções iriam apenas ter como argumento um XmlReader, e deveriam devolver uma instancia do objecto pretendido, ou seja, a função de departamentos devolver um Departamento e a função de empregado devolver um Empregado.

O que controlava o chamamento dessas funções ia ser a tua função principal, a que tem o while(reader.read()),  no switch, se o nodo for do tipo Element é porque é um nodo que queres processar, no xml de exemplo, seria ou um departamento ou um empregado,qualquer um deles ias criar um novo XmlReader através do método ReadSubTree, e evocavas então a tua função de processar nodos dando como argumento o novo XmlReader, este reader só te vai servir mesmo para ler o nodo, quando fizeres .Read() e já teres chegado ao fim do nodo ele devolve-te false. E quando fechares esse XmlReader e voltares para o original (supostamente já com um novo Departamento ou Empregado) o teu XmlReader original já irá estar posicionado no fim do nodo que acabaste de ler.

Isto tudo parece estar um pouco confuso. Qual é a vantagem? É que assim divides a lógica de leitura do Xml em várias funções, cada função irá ter acesso a um XmlReader que terá apenas a capacidade para ler aquele nodo especifico, não sendo necessário preocupar-se com outros casos externos. Tornado todo o trabalho mais simplificado.

Edit:

Outra coisa, se calhar em vez de List<Departamento> faria antes Dictionary<String, Departamento> sendo a key a chave do departamento no xml. Assim na altura de processar os Empregados tornava a procura do Departamento simplificada.

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Link to comment
Share on other sites

boas,

bem desde já obrigada! o que acabaste de falar foi o que tive a pensar todo o jantar!e acho que me ajudaste a confirmar que vou pelo caminho certo!

Apesar que talvez existam outros caminhos por onde ir, até mais simples!não sei, pelos conhecimentos que tenho neste momento, optei por aqui....

Em relação ao Dictionary, eu não tenho conhecimentos sobre tal, ainda não cheguei lá! :dontgetit:, mas já tinha me apercebido da sua existência, pode ser que em breve tenha um tempinho para analisar isso ( vou ter que ter  ? )

vou tentar implementar o que tenho em mente! mas tenho que ter muita atenção a forma como vou processar a informação, para não ocorrer atrasos de leitura no xml.

Estava a pensar, em passar por referência o objecto do XmlReader, mas isso não será bom, pois teria que começar a ler do inicio!Vou ver e depois apresento!

bom trabalho

tofas

Link to comment
Share on other sites

Em relação ao Dictionary, eu não tenho conhecimentos sobre tal, ainda não cheguei lá! :dontgetit:, mas já tinha me apercebido da sua existência, pode ser que em breve tenha um tempinho para analisar isso ( vou ter que ter  ? )

Sugeri o Dictionary, porque permite-te facilitar o código na altura de criar um Empregado. Porque quando no xml tens uma referencia ao departamento, terás que percorrer a lista para obter o departamento que pretendes. Com o Dictionary é imediato, o Dictionary é como uma HashTable.

vou tentar implementar o que tenho em mente! mas tenho que ter muita atenção a forma como vou processar a informação, para não ocorrer atrasos de leitura no xml.

Atrasos de leitura não acontecerá, o XmlReader garante-te isso, visto que só é possivel ler para frente. Ou seja, se já leste uma secção e ignoras-te, chapéu.. não podes voltar a lê-la.
Estava a pensar, em passar por referência o objecto do XmlReader, mas isso não será bom, pois teria que começar a ler do inicio!Vou ver e depois apresento!
Por isso é que disse para usares o método ReadSubTree(), já que isso dá-te uma nova instância de XmlReader só para ler o nodo de Xml que estás a processar, isolando a lógica desse nodo do resto do XML.

Boa sorte..

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Link to comment
Share on other sites

Venho aqui só deixar uma dica sobre uma coisa que aprendi há pouco tempo ....

 ....."C:\\Documents and Settings\\SMSilva\\Desktop\\Exemplo Teste\\projecto teste\\Project1\\Project1\\Tofas.xsd");

Para evitares as duplas barras e assim basta colocares uma @ antes ... É apenas um pormenor mas penso que é útil e interessante... e evita trabalho.. 

Fica aqui um link que explica isso...

http://blogs.msdn.com/csharpfaq/archive/2004/03/12/88414.aspx

Um blog :Sem Cafeína

Link to comment
Share on other sites

Bem pessoal, eu já tive a tentar fazer algumas coisas, mas tenho que ir dormir! Que já não aguento de cansaço  😞

Amanhã vou ver tudo com muita calma! e tenho que analisar o Dicionary e o ReadSubTree

Obrigada!Todas as dicas são importantes!

tofas

Link to comment
Share on other sites

Boas,

bem eu não estou a conseguir nada de jeito  :wallbash:


while (reader.Read())
            {
                reader.ReadToFollowing("Company");
                Console.WriteLine(reader.Name + " " + reader.Value);

                // Read the attributes
                while (reader.MoveToNextAttribute())
                {
                    if (reader.Name == "nome")
                    {
                        Console.WriteLine(reader.Name + " " + reader.Value);
                        empresa.Nome = reader.Value;
                    }
                    if (reader.Name == "contribuinte")
                    {
                        Console.WriteLine(reader.Name + " " + reader.Value);
                        empresa.Contribuinte = int.Parse(reader.Value);
                    }
                }
             
                reader.ReadToFollowing("departamentos");
                Console.WriteLine(reader.Name + " " + reader.Value);
                reader.ReadToFollowing("departamento");
                Console.WriteLine(reader.Name + " " + reader.Value);
                lerDepart(reader.ReadSubtree());

                //Departamento dep=lerDepart(reader.ReadSubtree());
                reader.ReadToFollowing("empregados");
                Console.WriteLine(reader.Name + " " + reader.Value);
                reader.ReadToFollowing("empregado");
                Console.WriteLine(reader.Name + " " + reader.Value);
              
            }



não está bem...  😞

bom trabalho

tofas

Link to comment
Share on other sites

Num programa que fiz há uns tempos com C#+XML também tive que ler de XML para um objecto, no caso um Aluno.

A parte de leitura foi conseguída desta forma:

            Aluno a = new Aluno();
            XmlTextReader reader = new XmlTextReader(Application.StartupPath+"\\XMLFiles\\alunos.xml");
            
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element)
                {
                    if (reader.Name == "aluno")  // aqui seria o teu empregado, por exemplo...
                    {
                       /*  aqui ficaria a leitura dos atributos (que eu não tive esse problema)  */

                        reader.Read();
                        while (reader.Name != "aluno") 
                        {
                            switch (reader.Name)
                            {
                                case "imagem": a.imagemURL = reader.ReadElementContentAsString();
                                    break;
                                case "nome": a.nome = reader.ReadElementContentAsString();
                                ....

No meu caso ia lendo alunos. Enquanto estivesse na tag aluno lia as tags do referido aluno (nome, morada, idade, etc.). Acabando esse aluno (chegando à tag <\aluno>) adicionava o objecto a a um vector de alunos.

-------------

Enquanto estiveres com o reader nas tags com atributos podes ler esses atributos da seguinte forma:

XML -> <tagzinha euSouUmAtributo="12">Texto</tagzinha>

reader.GetAttribute("euSouUmAtributo"); // retorna o 12

Não sei se é bem nestas coisas que estás com dificuldade.  😞

Link to comment
Share on other sites

boas,

mobes o que apresentaste, pareceu-em interessante  e fácil de perceber, e acho que vai ajudar para implementar o que quero, pois de uma forma diferente mas semelhantes, fizeste algo que eu quero implementar!

bem neste momento tenho algo assim:



while (reader.Read())
             {
                if (reader.IsStartElement())
                {
                    if (reader.IsEmptyElement)
                    {
                        Console.Write("<{0}", reader.Name);
                        if (reader.HasAttributes)
                        {
                           
                            while (reader.MoveToNextAttribute())
                            {
                                Console.Write(" {0}={1}", reader.Name, reader.Value);
                            }
                            // Move the reader back to the element node.
                            reader.MoveToElement();
                        }
                        Console.WriteLine("/>");
                    }
                    else
                    {
                        Console.Write("<{0} ", reader.Name);
                        if (reader.HasAttributes)
                        {
                            
                            while (reader.MoveToNextAttribute())
                            {
                                Console.WriteLine(" {0}={1}", reader.Name, reader.Value);
                            }
                            Console.WriteLine(">");
                            // Move the reader back to the element node.
                            reader.MoveToElement();
                        }
                        //reader.Read(); // Read the start tag.
                        if (reader.IsStartElement())  // Handle nested elements.
                            Console.Write("\r\n<{0}", reader.Name);
                        if (reader.HasAttributes)
                        {
                            while (reader.MoveToNextAttribute())
                            {
                                Console.WriteLine(" {0}={1}", reader.Name, reader.Value);
                            }
                            // Move the reader back to the element node.
                            reader.MoveToElement();
                        }
                        Console.WriteLine(">");
                        Console.WriteLine(reader.ReadString());  //Read the text content of the element.
                    }

                }
            }

aqui já tenho mais controlo da informação que se vai lendo....leio e escrevo o que quero malipular e agora vou tentar implementar para cada classe. E ai vou pensar como pensaste

                           switch (reader.Name)
                            {
                                case "imagem": a.imagemURL = reader.ReadElementContentAsString();
                                    break;
                                case "nome": a.nome = reader.ReadElementContentAsString();
                                ....

vou continuar a ver se é desta!

Bom trabalho

tofas

Link to comment
Share on other sites

Eu estava a pensar em desenvolver mais do género:

private void processaMainXml(XmlReader reader) {
   while( reader.Read()) {
      switch( reader.NodeType) {
         case XmlNodeType.Element:
            switch(reader.Name) {
                case "departamento":
                   Departamento dep = processaDepartamentoXml(reader.ReadSubTree());
                   this.AdicionaDepartamento(dep);
                   break;
                case "empregado":
                   Empregado emp = processaEmpregadoXml(reader.ReadSubTree());
                   this.AdicionaEmpregado(emp);
                   break;
                // etc ...
            }
            break;
         // etc..
      }
   }
}

private Departamento processaDepartamentoXml(XmlReader reader) {
   reader.MoveToNextAttribute();
   String nome = reader.Value;

   reader.MoveToNextAttribute();
   String id = reader.Value;
   
   return new Departamento(nome, id);
}

private Empregado processaEmpregadoXml(XmlReader reader) {
   reader.MoveToNextAttribute();
   Departamento dep = this.GetDepartamento(reader.Value);

   reader.MoveToElement();
   reader.ReadToFollowing("nome");
   String nome = reader.ReadInnerXml();
   reader.ReadToFollowing("funcao");
   String funcao = reader.ReadInnerXml();

   return new Empregado(nome, funcao, dep);
}

Bem acho que dá para passar a ideia... Acho que fica muito mais melhor bom do que encadeamento de ifs 😉

[Warning]Código não testado...[/Warning]

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Link to comment
Share on other sites

Boas,

eu só agora tive a ver o que apresentaste, e vou ver melhor a ideia..

Já consegui usar o reader.ReadSubTree() passando por argumento de um método que tem algo do género:

if (xr.IsStartElement())
            {
                //reading the attributes
                if (xr.HasAttributes)
                {
                    while (xr.MoveToNextAttribute())
                    {                        
                        switch (xr.Name)
                        {
                            case "id":
                                id = xr.Value;
                                break;
                            case "name":
                                name = xr.Value;
                                break;
                        }
                    }
                }
            }

eu também queria poder criar os objectos departamento e empregado como fazes, mas eu so consigo criar esses objectos através da empresa, o que me dificulta a vida e muito!E isso tem originado alguns problemas....

bem ver se em breve consigo ter algo de jeito!

bom trabalho

tofas

Link to comment
Share on other sites

eu também queria poder criar os objectos departamento e empregado como fazes, mas eu so consigo criar esses objectos através da empresa, o que me dificulta a vida e muito!E isso tem originado alguns problemas....

Não percebi. Podes exemplificar um pouco para ver se te consigo ajudar.

Podes no minimo tentar fazer isso com o auxilio de clousures, mas provavelmente não precisas de algo tao complicado.

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Link to comment
Share on other sites

Boas,

bem contornei o problema com algo so género:

tenho no método principal

       

  // Create the XmlSchemaSet class.
            XmlSchemaSet mySchema = new XmlSchemaSet();

            // Add the schema to the collection.
            mySchema.Add(null, xmlSchema);

            // Set the validation settings.
            XmlReaderSettings settings = readSettings;
            settings.IgnoreWhitespace = true;
            settings.IgnoreComments = true;
            settings.CheckCharacters = true;
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = mySchema;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

            // Create the XmlReader object.
            XmlReader reader = XmlReader.Create(xmlFile, settings);

            // starting to read the xml document
              reader.ReadToFollowing("Empresa");
	Empresa empresa= ReadEmpresa(reader.ReadSubtree());

	reader.ReadToFollowing("empregados");
	reader.ReadToFollowing("empregado");
              ReadEmpregado(empresa ,reader.ReadSubtree());
	...

e um dos métodos que vai ser chamado:

private void ReadEmpregado(Empresa empresa, XmlReader xr)
        {
            string name = "";
            int id = 0;
		string notes="";
            Empresa emp = empresa;

            if (xr.IsStartElement())
            {
         
                if (xr.HasAttributes)
                {
                    while (xr.MoveToNextAttribute())
                    {
                        switch (xr.Name)
                        {
                            case "id":
                                id = int.Parse(xr.Value);
                                break;
                            case "name":
                                name = xr.Value;
                                break;
                        }
                    }
            
                    xr.ReadToFollowing("notes");
                    if (xr.Name == "notes")
                    {
                        xr.Read();
                        notes = xr.Value;
                        xr.Read();
                        if (xr.NodeType == XmlNodeType.EndElement)
                        {
                            xr.Read();
                        }
                    }
                }
            }			

   // crio o objecto empregado através da empresa, dou como entrado o id, 
           //para actualizar o nextID - que é static!
            Empregado empregado = emp.LoadNode(id); 
            empregado .Name = name;
            empregado .ShortName = shortname;
            empregado .Notes = notes;
    }

atenção retirar só a  ideia, pois tive que adaptar ao problema que tenho, que é muito complexo e não poderei expor....  :dontgetit:

bom trabalho

tofas

Link to comment
Share on other sites

  • 4 months later...

Boas:

Provavelmente ja venho um bocado tarde, mas esta foi a melhor solução que encontrei para ler informação de um XML:

Não sei se falta alguma coisa mas em principio da para ter uma ideia...

O objectivo disto era ir buscar o valor do elemento "/Order/OrderHeader/OrderNumber/BuyerOrderNumber" e guarda-lo numa var.

Para varios elementos, fiz exactamente a mm coisa só que armazenei dentro de um objecto essas informações

XPathDocument doc = new XPathDocument(caminhoFicheiro);
XPathNavigator nav = doc.CreateNavigator();

nEncomenda = getInfo(nav, "/Order/OrderHeader/OrderNumber/BuyerOrderNumber"); // navegação nos elementos XML

      // blablablablablablablablablablablablablablablablablabla

        public static string getInfo(XPathNavigator nav, string caminho)
        {
            XPathExpression expr;
            expr = nav.Compile(caminho);
            XPathNodeIterator iterator = nav.Select(expr);

            try
            {
                while (iterator.MoveNext())
                {
                    XPathNavigator nav2 = iterator.Current.Clone();
                    return nav2.Value;
                }
            }
            catch (Exception ex)
            {
                this.SetText(ex.Message);
                return null;
            }
            return null;
        }

Qdo começei a resolver este problema, tb começei por utilizar o xml reader (foi o primeiro q consegui encontrar) mas n me fiquei por aqui pois esta classe só lê  para a frente, e em xml's mto complexos (como o meu e provavelmente o teu) iria complicar bastante as coisas para a frente.

Do que aprendi nisto e que existem 1000 modos de fazer as coisas... e não ficar pela 1º ou 2º resultado do google...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.