none
como carregar um xml com relacionamentos sem chave primária? RRS feed

  • Pergunta

  • olá galera

    estou com uma dificuldade, preciso importar arquivos xml da nfse, porém não sei como selecionar os ítens de cada nota sem ter algum dado em comum no nó <NOTA> e <ITEM>, segue um modelo bem resumido do XML, ele é exportado por data de emissão, então existem várias notas num mesmo arquivo:

    <?xml version="1.0" encoding="UTF-8"?>
    <NOTAS>
    	<VERSAO>1.00</VERSAO>
    	<NOTA>
    		<NUMERO>192</NUMERO>
    		<CNPJ>123456789</CNPJ>
    		<DT_COMPETENCIA>2012-02-03</DT_COMPETENCIA>
    		<DISCRIMINACAO>MEDIÇÃO DE SERVIÇOS REFERENTE FUNDAÇÃO E ALICERCES.</DISCRIMINACAO>
    		<VL_SERVICO>1234.56</VL_SERVICO>
    		<TOM_CPF_CNPJ>123456789</TOM_CPF_CNPJ>
    		<TOM_RAZAO_SOCIAL>TESTE TESTE </TOM_RAZAO_SOCIAL>
    		<LISTA_ITENS>
    			<ITEM>
    				<DESCRICAO>TESTE TESTE </DESCRICAO>
    				<QT_ITEM>1.00000</QT_ITEM>
    				<VL_UNITARIO>1234.56</VL_UNITARIO>
    				<SN_ISS_TRIBUTAVEL>1</SN_ISS_TRIBUTAVEL>
    			</ITEM>
    		</LISTA_ITENS>
    	</NOTA>
    	<NOTA>
    		<NUMERO>193</NUMERO>
    		<CNPJ>123456789</CNPJ>
    		<DT_COMPETENCIA>2012-02-03</DT_COMPETENCIA>
    		<DISCRIMINACAO>MEDIÇÃO DE SERVIÇOS REFERENTE FUNDAÇÃO E ALICERCES.</DISCRIMINACAO>
    		<VL_SERVICO>2469.12</VL_SERVICO>
    		<TOM_CPF_CNPJ>123456789</TOM_CPF_CNPJ>
    		<TOM_RAZAO_SOCIAL>TESTE TESTE </TOM_RAZAO_SOCIAL>
    		<LISTA_ITENS>
    			<ITEM>
    				<DESCRICAO>TESTE TESTE </DESCRICAO>
    				<QT_ITEM>1.00000</QT_ITEM>
    				<VL_UNITARIO>1234.56</VL_UNITARIO>
    				<SN_ISS_TRIBUTAVEL>1</SN_ISS_TRIBUTAVEL>
    			</ITEM>
    			<ITEM>
    				<DESCRICAO>TESTE TESTE </DESCRICAO>
    				<QT_ITEM>1.00000</QT_ITEM>
    				<VL_UNITARIO>1234.56</VL_UNITARIO>
    				<SN_ISS_TRIBUTAVEL>1</SN_ISS_TRIBUTAVEL>
    			</ITEM>
    		</LISTA_ITENS>
    	</NOTA>
    	<NOTA>
    		<NUMERO>194</NUMERO>
    		<CNPJ>123456789</CNPJ>
    		<DT_COMPETENCIA>2012-02-03</DT_COMPETENCIA>
    		<DISCRIMINACAO>MEDIÇÃO DE SERVIÇOS REFERENTE FUNDAÇÃO E ALICERCES.</DISCRIMINACAO>
    		<VL_SERVICO>1234.56</VL_SERVICO>
    		<TOM_CPF_CNPJ>123456789</TOM_CPF_CNPJ>
    		<TOM_RAZAO_SOCIAL>TESTE TESTE </TOM_RAZAO_SOCIAL>
    		<LISTA_ITENS>
    			<ITEM>
    				<DESCRICAO>TESTE TESTE </DESCRICAO>
    				<QT_ITEM>1.00000</QT_ITEM>
    				<VL_UNITARIO>1234.56</VL_UNITARIO>
    				<SN_ISS_TRIBUTAVEL>1</SN_ISS_TRIBUTAVEL>
    			</ITEM>
    		</LISTA_ITENS>
    	</NOTA>
    </NOTAS>

    a rotina q usei para abrir o xml foi:

    xmlfile = XmlReader.Create(TextBox1.Text, New XmlReaderSettings())
    
    
            ds.Clear()
    
            ds.ReadXml(xmlfile)
    
            DataGridView1.DataSource = ds.Tables("NOTA")
    
            DataGridView2.DataSource = ds.Tables("ITEM")

    até aí abriu nas datagrids, uma é para a nota e outra para os itens, abriu na mesma ordem, porém fiz uma alteração neste xml da nota 192 contendo dois itens nela, como vou saber quem são e quantos são os ítens da nota 192?

    quinta-feira, 23 de fevereiro de 2012 20:05

Respostas

  • yae Paulo blza?

    então consegui inserir os numeros das notas em cada ítem usando for each, de uma olhada, mas acho q fiz uma volta desnecessária q é a de carregar o arquivo xml 2 vezes, é pq aproveitei o código q havia implementado anteriormente

            ds.Clear()
            xmlfile = XmlReader.Create(TextBox1.Text, New XmlReaderSettings())
            ds.ReadXml(xmlfile)
            'Cria uma tabela para inserir os ítens com o número da nota como chave estrangeira
            ds.Tables.Add("ITENSNOTA")
            With ds.Tables("ITENSNOTA")
                .Columns.Add("NUMERO")
                .Columns.Add("DESCRICAO")
                .Columns.Add("QT_ITEM")
                .Columns.Add("VL_UNITARIO")
                .Columns.Add("SN_ISS_TRIBUTAVEL")
            End With
    
            Dim arquivoXML As New XmlDocument
            arquivoXML.Load(TextBox1.Text)
            Dim NOTA As Xml.XmlNode
            Dim ITEM As Xml.XmlNode
    
            'Itens
            For Each NOTA In arquivoXML.SelectNodes("NOTAS/NOTA")
    
                Dim NUMERO = NOTA.SelectSingleNode("NUMERO").InnerText
    
                MsgBox("qtd de itens = " & NOTA.LastChild.ChildNodes.Count)
    
                If NOTA.LastChild.ChildNodes.Count > 1 Then
    
                    For Each ITEM In NOTA.SelectNodes("LISTA_ITENS/ITEM")
    
                        With ds.Tables("ITENSNOTA")
                            .Rows.Add(NUMERO, ITEM.SelectSingleNode("DESCRICAO").InnerText, ITEM.SelectSingleNode("QT_ITEM").InnerText, ITEM.SelectSingleNode("VL_UNITARIO").InnerText, ITEM.SelectSingleNode("SN_ISS_TRIBUTAVEL").InnerText)
                        End With
    
                    Next
    
                Else
    
                    With ds.Tables("ITENSNOTA")
                        .Rows.Add(NUMERO, NOTA.LastChild.LastChild.SelectSingleNode("DESCRICAO").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("QT_ITEM").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("VL_UNITARIO").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("SN_ISS_TRIBUTAVEL").InnerText)
                    End With
    
                End If
    
            Next
    
            DataGridView1.DataSource = ds.Tables("NOTA")
    
            DataGridView2.DataSource = ds.Tables("ITENSNOTA")

    vlw

    muito obrigado pela dica!


    • Editado andremedeiross segunda-feira, 27 de fevereiro de 2012 17:27
    • Marcado como Resposta andremedeiross segunda-feira, 27 de fevereiro de 2012 17:31
    segunda-feira, 27 de fevereiro de 2012 17:25

Todas as Respostas

  • Eu te faço a mesma pergunta: como saber o "que é de que" se você não tem nada em comun? Tente conversar com a pessoa responsável por gerar o XML se existe alguma lógica. 

    Paulo César Viana
    .NET Developer
    MCC - Microsoft Community Contributor
    MCP - Microsoft Certified Professional
    MCTS - Microsoft Certified Technology Especialist
    --
    Marque as respostas e contribua para uma melhora no fórum.

    sexta-feira, 24 de fevereiro de 2012 13:22
  • realmente carregando o xml desta forma não da para encontrar nada em comum, será que existe alguma forma de carregar um nó por vez? pois assim eu saberia quais os ítens de cada nota.

    A minha intenção é importar o xml para um banco de dados, então se for possível carregar um nó <NOTA> por vez inclusive os nós filhos <ITEM> poderia importar tranquilamente os dados que preciso, na verdade não preciso de importar a nota inteira para o sistema, apenas o número da nota, os impostos, os ítens e o valor de cada ítem com os respectivos impostos de cada ítem.

    segunda-feira, 27 de fevereiro de 2012 11:22
  • Carregue ele apenas de uma vez, com você já está fazendo. Para acessar cada "nota" você vai usar um foreach normal.


    Paulo César Viana
    .NET Developer
    MCC - Microsoft Community Contributor
    MCP - Microsoft Certified Professional
    MCTS - Microsoft Certified Technology Especialist
    --
    Marque as respostas e contribua para uma melhora no fórum.

    segunda-feira, 27 de fevereiro de 2012 13:05
  • hm, boa idéia, vamos ver se com foreach eu consigo separar os ítens de cada nota

    vou testar e posto aqui o resultado!

    vlw

    segunda-feira, 27 de fevereiro de 2012 13:40
  • yae Paulo blza?

    então consegui inserir os numeros das notas em cada ítem usando for each, de uma olhada, mas acho q fiz uma volta desnecessária q é a de carregar o arquivo xml 2 vezes, é pq aproveitei o código q havia implementado anteriormente

            ds.Clear()
            xmlfile = XmlReader.Create(TextBox1.Text, New XmlReaderSettings())
            ds.ReadXml(xmlfile)
            'Cria uma tabela para inserir os ítens com o número da nota como chave estrangeira
            ds.Tables.Add("ITENSNOTA")
            With ds.Tables("ITENSNOTA")
                .Columns.Add("NUMERO")
                .Columns.Add("DESCRICAO")
                .Columns.Add("QT_ITEM")
                .Columns.Add("VL_UNITARIO")
                .Columns.Add("SN_ISS_TRIBUTAVEL")
            End With
    
            Dim arquivoXML As New XmlDocument
            arquivoXML.Load(TextBox1.Text)
            Dim NOTA As Xml.XmlNode
            Dim ITEM As Xml.XmlNode
    
            'Itens
            For Each NOTA In arquivoXML.SelectNodes("NOTAS/NOTA")
    
                Dim NUMERO = NOTA.SelectSingleNode("NUMERO").InnerText
    
                MsgBox("qtd de itens = " & NOTA.LastChild.ChildNodes.Count)
    
                If NOTA.LastChild.ChildNodes.Count > 1 Then
    
                    For Each ITEM In NOTA.SelectNodes("LISTA_ITENS/ITEM")
    
                        With ds.Tables("ITENSNOTA")
                            .Rows.Add(NUMERO, ITEM.SelectSingleNode("DESCRICAO").InnerText, ITEM.SelectSingleNode("QT_ITEM").InnerText, ITEM.SelectSingleNode("VL_UNITARIO").InnerText, ITEM.SelectSingleNode("SN_ISS_TRIBUTAVEL").InnerText)
                        End With
    
                    Next
    
                Else
    
                    With ds.Tables("ITENSNOTA")
                        .Rows.Add(NUMERO, NOTA.LastChild.LastChild.SelectSingleNode("DESCRICAO").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("QT_ITEM").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("VL_UNITARIO").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("SN_ISS_TRIBUTAVEL").InnerText)
                    End With
    
                End If
    
            Next
    
            DataGridView1.DataSource = ds.Tables("NOTA")
    
            DataGridView2.DataSource = ds.Tables("ITENSNOTA")

    vlw

    muito obrigado pela dica!


    • Editado andremedeiross segunda-feira, 27 de fevereiro de 2012 17:27
    • Marcado como Resposta andremedeiross segunda-feira, 27 de fevereiro de 2012 17:31
    segunda-feira, 27 de fevereiro de 2012 17:25
  • Melhorei o código!

    agora eu só separo os campos que realmente preciso, e uso o dataset apenas para armazenar os dados já tratados, assim posso criar uma function do tipo dataset para retornar um dataset toda vez que for chamada

    para quem interessar o código é este:

    Dim ds As New DataSet
    
            'Tabela referente aos dados principais da nota fiscal
            ds.Tables.Add("NOTAFISCAL")
            With ds.Tables("NOTAFISCAL").Columns
                .Add("NUMERO")
                .Add("CNPJ")
                .Add("INSCRICAO_MUNICIPAL")
                .Add("CD_VERIFICACAO")
                .Add("CD_STATUS")
                .Add("DT_CANCELAMENTO")
                .Add("DT_COMPETENCIA")
                .Add("DISCRIMINACAO")
                .Add("VL_SERVICO")
                .Add("VL_DEDUCAO")
                .Add("VL_PIS")
                .Add("VL_COFINS")
                .Add("VL_INSS")
                .Add("VL_IR")
                .Add("VL_CSLL")
                .Add("SN_ISS_RETIDO")
                .Add("VL_ISS")
                .Add("VL_ISS_RETIDO")
                .Add("VL_OUTRAS_RETENCOES")
                .Add("VL_BASE_CALCULO")
                .Add("VL_ALIQUOTA")
                .Add("VL_LIQUIDO_NFSE")
                .Add("VL_DESCONTO_INCONDICIONADO")
                .Add("VL_DESCONTO_CONDICIONADO")
                .Add("AL_PIS")
                .Add("AL_COFINS")
                .Add("AL_INSS")
                .Add("AL_IR")
                .Add("AL_CSLL")
                .Add("TOM_CPF_CNPJ")
                .Add("TOM_RAZAO_SOCIAL")
                .Add("TOM_ENDERECO")
                .Add("TOM_ENDERECO_NUMERO")
                .Add("TOM_ENDERECO_COMPLEMENTO")
                .Add("TOM_ENDERECO_BAIRRO")
                .Add("TOM_ENDERECO_UF")
                .Add("TOM_ENDERECO_CEP")
                .Add("TOM_TELEFONE")
                .Add("TOM_EMAIL")
            End With
    
            'Cria uma tabela para inserir os ítens com o número da nota como chave estrangeira
            ds.Tables.Add("ITENSNOTA")
            With ds.Tables("ITENSNOTA").Columns
                .Add("NUMERO")
                .Add("DESCRICAO")
                .Add("QT_ITEM")
                .Add("VL_UNITARIO")
                .Add("SN_ISS_TRIBUTAVEL")
            End With
    
            'Carrega o arquivo XML
            Dim arquivoXML As New XmlDocument
            arquivoXML.Load(TextBox1.Text)
    
            Dim NOTA As Xml.XmlNode
            Dim ITEM As Xml.XmlNode
    
            Dim i As Integer = 0
    
            'Separando os dados da notafiscal
            For Each NOTA In arquivoXML.SelectNodes("NOTAS/NOTA")
    
                Dim NUMERO As Integer = NOTA.SelectSingleNode("NUMERO").InnerText
    
                'Insere os dados principais da NOTAFISCAL
                With ds.Tables("NOTAFISCAL")
                    .Rows.Add()
                    .Rows(i).Item("NUMERO") = NUMERO
    
                    For j As Integer = 0 To ds.Tables("NOTAFISCAL").Columns.Count - 1
                        .Rows(i).Item(j) = NOTA.SelectSingleNode(.Columns(j).ColumnName).InnerText
                    Next
    
                End With
    
                'Incrementa a linha para uma nova nota fiscal
                i += 1
    
                'Insere os ítens da nota fiscal na tabela ITENSNOTA
                If NOTA.LastChild.ChildNodes.Count > 1 Then
    
                    For Each ITEM In NOTA.SelectNodes("LISTA_ITENS/ITEM")
    
                        With ds.Tables("ITENSNOTA")
                            .Rows.Add(NUMERO, ITEM.SelectSingleNode("DESCRICAO").InnerText, ITEM.SelectSingleNode("QT_ITEM").InnerText, ITEM.SelectSingleNode("VL_UNITARIO").InnerText, ITEM.SelectSingleNode("SN_ISS_TRIBUTAVEL").InnerText)
                        End With
    
                    Next
    
                Else
    
                    With ds.Tables("ITENSNOTA")
                        .Rows.Add(NUMERO, NOTA.LastChild.LastChild.SelectSingleNode("DESCRICAO").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("QT_ITEM").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("VL_UNITARIO").InnerText, NOTA.LastChild.LastChild.SelectSingleNode("SN_ISS_TRIBUTAVEL").InnerText)
                    End With
    
                End If
    
            Next
    
            'Resultado
            DataGridView1.DataSource = ds.Tables("NOTAFISCAL")
            DataGridView2.DataSource = ds.Tables("ITENSNOTA")

    Caso possam melhorar o código ou alguma sugestão gostaria de ser reportado!

    vlw pessoal

    quarta-feira, 29 de fevereiro de 2012 17:06