Transformação de XML para TXT [RESOLVIDO]

1. Transformação de XML para TXT [RESOLVIDO]

Alexandre Rios
alex_tj

(usa Outra)

Enviado em 07/07/2023 - 10:55h

Pessoal bom dia, tudo bem?

Fiz uma extração de dados via estrutura WSDL e como retorno recebo uma string em XML, porém estou com alguns problemas pra transformar essa string no padrão de carga que preciso, que seria um arquivo .TXT separado por pipeline (|).

A string vem nesse formato:

<NomeCandidato>Nome ficticio 1</NomeCandidato><CPF>12345678900</CPF><IDInscricao>8523690</IDInscricao><DataExame>2009-10-02T00:00:00</DataExame><NomeExame>Ouvidores</NomeExame><DataProcessamento>2009-10-05T15:50:15.447</DataProcessamento><SituacaoFinal>R</SituacaoFinal><GrauObtido>63.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>25</NumeroAcertos><TempoRestante>2000-01-01T01:15:46</TempoRestante><CooperativaCentral>0000 - Instituição A</CooperativaCentral>
<NomeCandidato>Nome ficticio 2</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>9999.1 - PA - Singular 1</CooperativaSingular>

E as transformações que preciso aplicar são:
1. As informações que estão dentro das tags <...> e </...> precisam ser removidas pq elas apenas indicam o início e fim da coluna;

2. As colunas que não tiverem informação precisam ser marcadas normalmente com o separador escolhido o pipeline (|)
Exemplo:
- Na primeira linha da string acima, que coloquei como exemplo não possui informação para a coluna CooperativaSingular, o ideal era que o XML nesse caso destacasse a coluna dessa forma: <CooperativaSingular></CooperativaSingular>, porém na primeira linha simplesmente a tag não aparece, logo pra quê simplificar se eles podem dificultar? Com isso, mesmo não havendo nenhuma informação, na transformação final eu preciso saber que este campo é reservado e isso se aplica para todas as outras colunas que podem ser vazias ou não;

3. As colunas com características de date ou datetime devem estar no formato YYYY-MM-DD;

4. Por fim, deve-se incluir o cabeçalho abaixo: NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular

A ideia é que com as transformações acima feitas as linhas fiquem assim:

NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular
Nome ficticio 1|12345678900|8523690|2009-10-02|Ouvidores|2009-10-05|R|63.00|Resultado Fornecido/Liberado|0|25|2000-01-01|0000 - Instituição A|
Nome ficticio 2|14785236900|9874561|2023-05-12|CPC-S100|2023-05-14|A|77.00|Resultado Fornecido/Liberado|0|46|2000-01-01|9999 - Instituição B|9999.1 - PA - Singular 1

O arquivo tem 50.000 linhas e o que fiz até agora foi essa parte de código:

#!/bin/bash

# Parâmetros externos
caminho="$1"
interface="$2"

# Definir a data atual no formato "YYYYMMDD"
data=$(date -d "$(date +%Y-%m-01) -1 month" "+%Y%m%d")

# Extrair os dados de resposta
echo "Extraindo dados de resposta..."
retorno=$(grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p')

# Verificar se existem dados de resultado
hasData=false
if [ -n "${retorno}" ] && [ "${retorno}" != "None" ]; then
hasData=true
fi

# Verificar se há dados
if [ "${hasData}" = true ]; then
echo "Dados encontrados. Gerando arquivo de saída..."

# Definir o cabeçalho
header="NomeCandidato|CPF|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular|IDInscricao|DataExame"

# Definir o nome do arquivo de saída
arquivo_saida="${caminho}/ARQUIVO_FINAL_${interface}_${data}.TXT"

# Escrever o cabeçalho no arquivo
echo "${header}" > "${arquivo_saida}"

# Substituir <DadosResultado> por vazio e </DadosResultado> por \n
echo "${retorno}" | sed 's|<DadosResultado>||g; s|<Dados>||g; s|</DadosResultado>|\n|g; s|</Dados>||g' >> "${arquivo_saida}"

echo "Arquivo de saída gerado em: ${arquivo_saida}"
else
echo "Nenhum dado encontrado."
fi

dos2unix "${arquivo_saida}"
rm -f "${caminho}/response.xml"

echo "Conversão para formato UNIX concluída."


No mais é isso, se puderem me ajudar agradeço demais!!!!!


Abraço.


  


2. MELHOR RESPOSTA

Marcelo Oliver
msoliver

(usa Debian)

Enviado em 08/07/2023 - 21:49h

alex_tj escreveu:


msoliver escreveu:

Boa noite Alexandre.
Vamos por partes....
Com o comando:
grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p' 

Vc "pega" todo o arquivo, eliminando "<ObterResultadosInicioResult>" e "</ObterResultadosInicioResult>"
É isso?
----------------------------------------------------------------------------------------------------------------
Realmente, o maior problema são os campos inexistentes ....
Vejo que o ideal é padronizar o arquivo.
Sugestão:
Checar os campos a partir da var "$header"...
Fiz um teste, e o resultado foi satisfatório.
Por hora, a saída é essa:
./script.sh
-------------------------
Checar campos do Reg:1 Cmp:14
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: ok
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: not
IDInscricao: ok
DataExame: ok

Reg:00002 Campos:15 Okay
-------------------------
Checar campos do Reg:3 Cmp:13
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: not
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: ok
IDInscricao: not
DataExame: ok


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________


Marcelo no XML existe uma tag que é essa: ObterResultadosInicioResult que determina o início e o fim da action, pq o SOAP ele traz várias informações na string do XML aí eu restrinjo pra pegar tudo o que está dentro disso --> <ObterResultadosInicioResult> ..... </ObterResultadosInicioResult> que é efetivamente os dados que preciso trabalhar.

E minha ideia é justamente tentar comparar linha a linha com o cabeçalho, mesmo sabendo que pode ser que isso deixe o processo lento, mas o desafio realmente é marcar o vazio na linha com o ||

Em python eu fazia isso e funcionava perfeitamente:
......
Só que em ambiente corporativo existem algumas bibliotecas que usava que não poderia ser instaladas e por isso estou migrando o código para shell script.
Obrigado pela ajuda!


Alexandre, boa noite.
Entendi sobre a 'tag' ObterResultadosInicioResult,
fiz os testes sem ela, e com um registro por linha,conforme arquivo abaixo.
"Parece" que funcionou.....
cat response.xml
<NomeCandidato>AAAA</NomeCandidato><CPF>12345678900</CPF><IDInscricao>8523690</IDInscricao><DataExame>2009-10-02T00:00:00</DataExame><NomeExame>Ouvidores</NomeExame><DataProcessamento>2009-10-05T15:50:15.447</DataProcessamento><SituacaoFinal>R</SituacaoFinal><GrauObtido>63.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>25</NumeroAcertos><TempoRestante>2000-01-01T01:15:46</TempoRestante><CooperativaCentral>0000 - Instituição A</CooperativaCentral>
<NomeCandidato>BBBB</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>Singular 2</CooperativaSingular>
<NomeCandidato>CCCC</NomeCandidato><CPF>78523654100</CPF><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>Coop 1</CooperativaCentral><CooperativaSingular>Singular 3</CooperativaSingular>
<NomeCandidato>DDDD</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>Singular 4</CooperativaSingular>
<NomeCandidato>ABCD</NomeCandidato><CPF>78523654100</CPF><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-ABCD</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>Coop 1</CooperativaCentral><CooperativaSingular>Singular 5</CooperativaSingular>
<NomeCandidato>WXYZ</NomeCandidato><CPF>78523654100</CPF>


Script:

#!/usr/bin/env bash
NR=0;
header="NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular"
arr=(${header//|/ });
arqen='response.xml';
arqsa=$(printf 'ARQUIVO_FINAL_%(%Y%m%d)T.txt');

#Llimpa arq
sed -i.bak 's/<[[:alpha:]]\+>//g;' ${arqen}

#altera formato da data:
sed -ri 's/T[0-9:.]+//g' ${arqen}

#Insere Cabeçalho
echo $header > ${arqsa};

while read line;do
NC=$(awk -F"</[[:alpha:]]+>" '{print NF}' <<< "$line");
echo "Reg:$((++NR)) Campos:$NC";
if (($NC == 15));then
awk -F"</[[:alpha:]]+>" '{OFS="|"; print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}' <<< "$line" >> ${arqsa}
else
unset res ttr;
for ((n=0;n<${#arr[@]};n++));do
res=$(grep -Eo "[[:alnum:]._-]+</${arr[$n]}>" <<< "$line");
ttr+="${res/<\/${arr[$n]}>/}|";
done
echo "${ttr}" >> ${arqsa}
fi
done<${arqen}

sed -i 's/|$//' ${arqsa}

Arquivo_final
NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular
AAAA|12345678900|8523690|2009-10-02|Ouvidores|2009-10-05|R|63.00|Liberado|0|25|2000-01-01|A|
BBBB|14785236900|9874561|2023-05-12|CPC-S100|2023-05-14|A|77.00|Resultado Fornecido/Liberado|0|46|2000-01-01|9999 - Instituição B|Singular 2
CCCC|78523654100||2023-05-12|CPC-S100|2023-05-14|A||Liberado|0|46|2000-01-01|1|3
DDDD|14785236900|9874561|2023-05-12||2023-05-14|A|77.00|Liberado|0|46|2000-01-01|B|4
ABCD|78523654100||2023-05-12|CPC-ABCD|2023-05-14|A||Liberado|0|46|2000-01-01|1|5
WXYZ|78523654100||||||||||||

-----------------------------------------
É isso.....


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________


3. Re: Transformação de XML para TXT [RESOLVIDO]

Marcelo Oliver
msoliver

(usa Debian)

Enviado em 07/07/2023 - 17:38h


alex_tj escreveu:

Pessoal bom dia, tudo bem?

Fiz uma extração de dados via estrutura WSDL e como retorno recebo uma string em XML, porém estou com alguns problemas pra transformar essa string no padrão de carga que preciso, que seria um arquivo .TXT separado por pipeline (|).

A string vem nesse formato:

<NomeCandidato>Nome ficticio 1</NomeCandidato><CPF>12345678900</CPF><IDInscricao>8523690</IDInscricao><DataExame>2009-10-02T00:00:00</DataExame><NomeExame>Ouvidores</NomeExame><DataProcessamento>2009-10-05T15:50:15.447</DataProcessamento><SituacaoFinal>R</SituacaoFinal><GrauObtido>63.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>25</NumeroAcertos><TempoRestante>2000-01-01T01:15:46</TempoRestante><CooperativaCentral>0000 - Instituição A</CooperativaCentral>
<NomeCandidato>Nome ficticio 2</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>9999.1 - PA - Singular 1</CooperativaSingular>

E as transformações que preciso aplicar são:
1. As informações que estão dentro das tags <...> e </...> precisam ser removidas pq elas apenas indicam o início e fim da coluna;

2. As colunas que não tiverem informação precisam ser marcadas normalmente com o separador escolhido o pipeline (|)
Exemplo:
- Na primeira linha da string acima, que coloquei como exemplo não possui informação para a coluna CooperativaSingular, o ideal era que o XML nesse caso destacasse a coluna dessa forma: <CooperativaSingular></CooperativaSingular>, porém na primeira linha simplesmente a tag não aparece, logo pra quê simplificar se eles podem dificultar? Com isso, mesmo não havendo nenhuma informação, na transformação final eu preciso saber que este campo é reservado e isso se aplica para todas as outras colunas que podem ser vazias ou não;

3. As colunas com características de date ou datetime devem estar no formato YYYY-MM-DD;

4. Por fim, deve-se incluir o cabeçalho abaixo: NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular

A ideia é que com as transformações acima feitas as linhas fiquem assim:

NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular
Nome ficticio 1|12345678900|8523690|2009-10-02|Ouvidores|2009-10-05|R|63.00|Resultado Fornecido/Liberado|0|25|2000-01-01|0000 - Instituição A|
Nome ficticio 2|14785236900|9874561|2023-05-12|CPC-S100|2023-05-14|A|77.00|Resultado Fornecido/Liberado|0|46|2000-01-01|9999 - Instituição B|9999.1 - PA - Singular 1

O arquivo tem 50.000 linhas e o que fiz até agora foi essa parte de código:

#!/bin/bash

# Parâmetros externos
caminho="$1"
interface="$2"

# Definir a data atual no formato "YYYYMMDD"
data=$(date -d "$(date +%Y-%m-01) -1 month" "+%Y%m%d")

# Extrair os dados de resposta
echo "Extraindo dados de resposta..."
retorno=$(grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p')

# Verificar se existem dados de resultado
hasData=false
if [ -n "${retorno}" ] && [ "${retorno}" != "None" ]; then
hasData=true
fi

# Verificar se há dados
if [ "${hasData}" = true ]; then
echo "Dados encontrados. Gerando arquivo de saída..."

# Definir o cabeçalho
header="NomeCandidato|CPF|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular|IDInscricao|DataExame"

# Definir o nome do arquivo de saída
arquivo_saida="${caminho}/ARQUIVO_FINAL_${interface}_${data}.TXT"

# Escrever o cabeçalho no arquivo
echo "${header}" > "${arquivo_saida}"

# Substituir <DadosResultado> por vazio e </DadosResultado> por \n
echo "${retorno}" | sed 's|<DadosResultado>||g; s|<Dados>||g; s|</DadosResultado>|\n|g; s|</Dados>||g' >> "${arquivo_saida}"

echo "Arquivo de saída gerado em: ${arquivo_saida}"
else
echo "Nenhum dado encontrado."
fi

dos2unix "${arquivo_saida}"
rm -f "${caminho}/response.xml"

echo "Conversão para formato UNIX concluída."


No mais é isso, se puderem me ajudar agradeço demais!!!!!


Abraço.

Boa tarde Alex.
Verifiquei seu script e surgiram duvidas...
A var retorno tem o arquivo de 50000 linhas.....?
Quantos campos tem um registro 'completo'?
No exemplo postado "2 registros", um tem 14 e o outro 15.
15 é o nº max de campos?


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________



4. Transformação de XML para TXT

Alexandre Rios
alex_tj

(usa Outra)

Enviado em 07/07/2023 - 19:33h

msoliver escreveu:


alex_tj escreveu:

Pessoal bom dia, tudo bem?

Fiz uma extração de dados via estrutura WSDL e como retorno recebo uma string em XML, porém estou com alguns problemas pra transformar essa string no padrão de carga que preciso, que seria um arquivo .TXT separado por pipeline (|).

A string vem nesse formato:

<NomeCandidato>Nome ficticio 1</NomeCandidato><CPF>12345678900</CPF><IDInscricao>8523690</IDInscricao><DataExame>2009-10-02T00:00:00</DataExame><NomeExame>Ouvidores</NomeExame><DataProcessamento>2009-10-05T15:50:15.447</DataProcessamento><SituacaoFinal>R</SituacaoFinal><GrauObtido>63.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>25</NumeroAcertos><TempoRestante>2000-01-01T01:15:46</TempoRestante><CooperativaCentral>0000 - Instituição A</CooperativaCentral>
<NomeCandidato>Nome ficticio 2</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>9999.1 - PA - Singular 1</CooperativaSingular>

E as transformações que preciso aplicar são:
1. As informações que estão dentro das tags <...> e </...> precisam ser removidas pq elas apenas indicam o início e fim da coluna;

2. As colunas que não tiverem informação precisam ser marcadas normalmente com o separador escolhido o pipeline (|)
Exemplo:
- Na primeira linha da string acima, que coloquei como exemplo não possui informação para a coluna CooperativaSingular, o ideal era que o XML nesse caso destacasse a coluna dessa forma: <CooperativaSingular></CooperativaSingular>, porém na primeira linha simplesmente a tag não aparece, logo pra quê simplificar se eles podem dificultar? Com isso, mesmo não havendo nenhuma informação, na transformação final eu preciso saber que este campo é reservado e isso se aplica para todas as outras colunas que podem ser vazias ou não;

3. As colunas com características de date ou datetime devem estar no formato YYYY-MM-DD;

4. Por fim, deve-se incluir o cabeçalho abaixo: NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular

A ideia é que com as transformações acima feitas as linhas fiquem assim:

NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular
Nome ficticio 1|12345678900|8523690|2009-10-02|Ouvidores|2009-10-05|R|63.00|Resultado Fornecido/Liberado|0|25|2000-01-01|0000 - Instituição A|
Nome ficticio 2|14785236900|9874561|2023-05-12|CPC-S100|2023-05-14|A|77.00|Resultado Fornecido/Liberado|0|46|2000-01-01|9999 - Instituição B|9999.1 - PA - Singular 1

O arquivo tem 50.000 linhas e o que fiz até agora foi essa parte de código:

#!/bin/bash

# Parâmetros externos
caminho="$1"
interface="$2"

# Definir a data atual no formato "YYYYMMDD"
data=$(date -d "$(date +%Y-%m-01) -1 month" "+%Y%m%d")

# Extrair os dados de resposta
echo "Extraindo dados de resposta..."
retorno=$(grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p')

# Verificar se existem dados de resultado
hasData=false
if [ -n "${retorno}" ] && [ "${retorno}" != "None" ]; then
hasData=true
fi

# Verificar se há dados
if [ "${hasData}" = true ]; then
echo "Dados encontrados. Gerando arquivo de saída..."

# Definir o cabeçalho
header="NomeCandidato|CPF|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular|IDInscricao|DataExame"

# Definir o nome do arquivo de saída
arquivo_saida="${caminho}/ARQUIVO_FINAL_${interface}_${data}.TXT"

# Escrever o cabeçalho no arquivo
echo "${header}" > "${arquivo_saida}"

# Substituir <DadosResultado> por vazio e </DadosResultado> por \n
echo "${retorno}" | sed 's|<DadosResultado>||g; s|<Dados>||g; s|</DadosResultado>|\n|g; s|</Dados>||g' >> "${arquivo_saida}"

echo "Arquivo de saída gerado em: ${arquivo_saida}"
else
echo "Nenhum dado encontrado."
fi

dos2unix "${arquivo_saida}"
rm -f "${caminho}/response.xml"

echo "Conversão para formato UNIX concluída."


No mais é isso, se puderem me ajudar agradeço demais!!!!!


Abraço.

Boa tarde Alex.
Verifiquei seu script e surgiram duvidas...
A var retorno tem o arquivo de 50000 linhas.....?
Quantos campos tem um registro 'completo'?
No exemplo postado "2 registros", um tem 14 e o outro 15.
15 é o nº max de campos?


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________



Fala Marcelo, tranquilo?

Na verdade 50.000 linhas é o total de linhas do XML, pois vem uma string gigantesca pois faço a extração dela dessa forma:

retorno=$(grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' ${caminho}/response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p')

A partir daí vou fazendo algumas transformações que não tem performado muito bem, para chegar no resultado final:

echo "${retorno}" | sed -e 's|<DadosResultado>||g' -e 's|<Dados>||g' -e 's|</DadosResultado>|\n|g' -e 's/<\([^>]*\)>/|/g' -e 's/||/|/g' | sed -e 's/^.//' | rev | cut -c 2- | rev | awk -F '|' -v OFS='|' '{
for (i=1; i<=NF; i++) {
if ($i ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}(T[0-9]{2}:[0-9]{2}(:[0-9]{2}(\.[0-9]+)?)?)?$/) {
cmd = "date -d \"" $i "\" +%Y-%m-%d"
cmd | getline value
close(cmd)
$i = value
}
}
print $0
}' >> "${arquivo_saida}"

E para esse arquivo final é isso mesmo são 15 colunas, como está no cabeçalho abaixo:
header="NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular"

O grande problema pra mim é pq não sei qual coluna pode vir em branco e no XML ao invés dele descrever a coluna mesmo com o espaço vazio ele faz igual ao exemplo, o XML ignora a existência dela e aí não sei como fazer para reservar o espaço vazio com || .

Por exemplo: Se IDInscricao e GrauObtido viessem vazios no XML estaria assim
<NomeCandidato>ABCD</NomeCandidato><CPF>78523654100</CPF><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>Coop 1</CooperativaCentral><CooperativaSingular>Singular 1.1</CooperativaSingular>

Mas o arquivo final teria que ter a saída dessa forma:
ABCD|78523654100||2023-05-12|CPC-S100|2023-05-14|A||Resultado Fornecido/Liberado|0|46|2000-01-01|Coop 1|Singular 1.1

Muito obrigado pela ajuda!


--
Alexandre R.



5. Re: Transformação de XML para TXT [RESOLVIDO]

Marcelo Oliver
msoliver

(usa Debian)

Enviado em 07/07/2023 - 23:03h

Boa noite Alexandre.
Vamos por partes....
Com o comando:
grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p' 

Vc "pega" todo o arquivo, eliminando "<ObterResultadosInicioResult>" e "</ObterResultadosInicioResult>"
É isso?
----------------------------------------------------------------------------------------------------------------
Realmente, o maior problema são os campos inexistentes ....
Vejo que o ideal é padronizar o arquivo.
Sugestão:
Checar os campos a partir da var "$header"...
Fiz um teste, e o resultado foi satisfatório.
Por hora, a saída é essa:
./script.sh
-------------------------
Checar campos do Reg:1 Cmp:14
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: ok
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: not
IDInscricao: ok
DataExame: ok

Reg:00002 Campos:15 Okay
-------------------------
Checar campos do Reg:3 Cmp:13
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: not
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: ok
IDInscricao: not
DataExame: ok


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________



6. Re: Transformação de XML para TXT

Buckminster
Buckminster

(usa Debian)

Enviado em 08/07/2023 - 03:12h

O Eclipse não gera e lê wsdl?
De repente você faz as alterações necessárias e salva como txt.

https://crunchify.com/create-sample-wsdl-in-eclipse-and-generate-client/


_________________________________________________________
Always listen the Buck!
Com raras exceções, não dou mais soluções prontas, somente dou dicas!


7. Re: Transformação de XML para TXT [RESOLVIDO]

Alexandre Rios
alex_tj

(usa Outra)

Enviado em 08/07/2023 - 05:53h


msoliver escreveu:

Boa noite Alexandre.
Vamos por partes....
Com o comando:
grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p' 

Vc "pega" todo o arquivo, eliminando "<ObterResultadosInicioResult>" e "</ObterResultadosInicioResult>"
É isso?
----------------------------------------------------------------------------------------------------------------
Realmente, o maior problema são os campos inexistentes ....
Vejo que o ideal é padronizar o arquivo.
Sugestão:
Checar os campos a partir da var "$header"...
Fiz um teste, e o resultado foi satisfatório.
Por hora, a saída é essa:
./script.sh
-------------------------
Checar campos do Reg:1 Cmp:14
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: ok
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: not
IDInscricao: ok
DataExame: ok

Reg:00002 Campos:15 Okay
-------------------------
Checar campos do Reg:3 Cmp:13
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: not
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: ok
IDInscricao: not
DataExame: ok


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________


Marcelo no XML existe uma tag que é essa: ObterResultadosInicioResult que determina o início e o fim da action, pq o SOAP ele traz várias informações na string do XML aí eu restrinjo pra pegar tudo o que está dentro disso --> <ObterResultadosInicioResult> ..... </ObterResultadosInicioResult> que é efetivamente os dados que preciso trabalhar.

E minha ideia é justamente tentar comparar linha a linha com o cabeçalho, mesmo sabendo que pode ser que isso deixe o processo lento, mas o desafio realmente é marcar o vazio na linha com o ||

Em python eu fazia isso e funcionava perfeitamente:

def getHeader():
return ("NomeCandidato", "CPF", "NomeExame", "DataProcessamento", "SituacaoFinal", "GrauObtido", "StatusLiberacao", "IDModulo", "NumeroAcertos", "TempoRestante", "CooperativaCentral", "CooperativaSingular","IDInscricao","DataExame")

def listatostring(linha):
novalinha=[]
colunas = getHeader()
for coluna in colunas:
valor = ""
if (coluna in linha):
valor = linha[coluna]
if isinstance(valor,datetime):
novalinha.append("{:%Y-%m-%d}".format(valor))
elif isinstance(valor,int):
novalinha.append(str(valor))
elif not isinstance(valor,str) and not isinstance(valor,datetime) and not isinstance(valor,int):
novalinha.append("{0:.3g}".format(valor))
else:
novalinha.append(valor)
return(novalinha)

hasData = False
retorno = response["ObterResultadosInicioResult"]
if "Dados" in retorno:
retorno=response["ObterResultadosInicioResult"]["Dados"]
if "DadosResultado" in retorno:
hasData = True
retorno=response["ObterResultadosInicioResult"]["Dados"]["DadosResultado"]
else:
print(response["ObterResultadosInicioResult"])

if (hasData):

header="|".join(getHeader())

with open('ARQUIVO_FINAL_{}.TXT'.format(dataarquivo), 'w',encoding='utf8') as arquivo:
arquivo.write(header)
arquivo.write("\n")
for linha in retorno:
dados = listatostring(linha)
arquivo.write("|".join(dados).strip())
arquivo.write("\n")


Só que em ambiente corporativo existem algumas bibliotecas que usava que não poderia ser instaladas e por isso estou migrando o código para shell script.

Obrigado pela ajuda!


8. Re: Transformação de XML para TXT [RESOLVIDO]

Alexandre Rios
alex_tj

(usa Outra)

Enviado em 08/07/2023 - 05:58h


Buckminster escreveu:

O Eclipse não gera e lê wsdl?
De repente você faz as alterações necessárias e salva como txt.

https://crunchify.com/create-sample-wsdl-in-eclipse-and-generate-client/


_________________________________________________________
Always listen the Buck!
Com raras exceções, não dou mais soluções prontas, somente dou dicas!


Fala Buckminster, tranquilo?

Eu uso um servidor que está instalado uma ferramenta chamada Datastage da IBM, lá não tenho acesso ao Eclipse, por isso preciso fazer tudo via script seja: Ruby, Python ou Shell sem utilização de nenhuma ferramenta terceira, para que o Datastage chame o script através de um componente Command e execute.

Mas de toda forma obrigado pela ajuda.

Abraço!


--
Alexandre R.


9. Re: Transformação de XML para TXT

Alexandre Rios
alex_tj

(usa Outra)

Enviado em 09/07/2023 - 00:31h

msoliver escreveu:

alex_tj escreveu:


msoliver escreveu:

Boa noite Alexandre.
Vamos por partes....
Com o comando:
grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p' 

Vc "pega" todo o arquivo, eliminando "<ObterResultadosInicioResult>" e "</ObterResultadosInicioResult>"
É isso?
----------------------------------------------------------------------------------------------------------------
Realmente, o maior problema são os campos inexistentes ....
Vejo que o ideal é padronizar o arquivo.
Sugestão:
Checar os campos a partir da var "$header"...
Fiz um teste, e o resultado foi satisfatório.
Por hora, a saída é essa:
./script.sh
-------------------------
Checar campos do Reg:1 Cmp:14
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: ok
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: not
IDInscricao: ok
DataExame: ok

Reg:00002 Campos:15 Okay
-------------------------
Checar campos do Reg:3 Cmp:13
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: not
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: ok
IDInscricao: not
DataExame: ok


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________


Marcelo no XML existe uma tag que é essa: ObterResultadosInicioResult que determina o início e o fim da action, pq o SOAP ele traz várias informações na string do XML aí eu restrinjo pra pegar tudo o que está dentro disso --> <ObterResultadosInicioResult> ..... </ObterResultadosInicioResult> que é efetivamente os dados que preciso trabalhar.

E minha ideia é justamente tentar comparar linha a linha com o cabeçalho, mesmo sabendo que pode ser que isso deixe o processo lento, mas o desafio realmente é marcar o vazio na linha com o ||

Em python eu fazia isso e funcionava perfeitamente:
......
Só que em ambiente corporativo existem algumas bibliotecas que usava que não poderia ser instaladas e por isso estou migrando o código para shell script.
Obrigado pela ajuda!


Alexandre, boa noite.
Entendi sobre a 'tag' ObterResultadosInicioResult,
fiz os testes sem ela, e com um registro por linha,conforme arquivo abaixo.
"Parece" que funcionou.....
cat response.xml
<NomeCandidato>AAAA</NomeCandidato><CPF>12345678900</CPF><IDInscricao>8523690</IDInscricao><DataExame>2009-10-02T00:00:00</DataExame><NomeExame>Ouvidores</NomeExame><DataProcessamento>2009-10-05T15:50:15.447</DataProcessamento><SituacaoFinal>R</SituacaoFinal><GrauObtido>63.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>25</NumeroAcertos><TempoRestante>2000-01-01T01:15:46</TempoRestante><CooperativaCentral>0000 - Instituição A</CooperativaCentral>
<NomeCandidato>BBBB</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>Singular 2</CooperativaSingular>
<NomeCandidato>CCCC</NomeCandidato><CPF>78523654100</CPF><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>Coop 1</CooperativaCentral><CooperativaSingular>Singular 3</CooperativaSingular>
<NomeCandidato>DDDD</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>Singular 4</CooperativaSingular>
<NomeCandidato>ABCD</NomeCandidato><CPF>78523654100</CPF><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-ABCD</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>Coop 1</CooperativaCentral><CooperativaSingular>Singular 5</CooperativaSingular>
<NomeCandidato>WXYZ</NomeCandidato><CPF>78523654100</CPF>


Script:

#!/usr/bin/env bash
NR=0;
header="NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular"
arr=(${header//|/ });
arqen='response.xml';
arqsa=$(printf 'ARQUIVO_FINAL_%(%Y%m%d)T.txt');

#Llimpa arq
sed -i.bak 's/<[[:alpha:]]\+>//g;' ${arqen}

#altera formato da data:
sed -ri 's/T[0-9:.]+//g' ${arqen}

#Insere Cabeçalho
echo $header > ${arqsa};

while read line;do
NC=$(awk -F"</[[:alpha:]]+>" '{print NF}' <<< "$line");
echo "Reg:$((++NR)) Campos:$NC";
if (($NC == 15));then
awk -F"</[[:alpha:]]+>" '{OFS="|"; print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}' <<< "$line" >> ${arqsa}
else
unset res ttr;
for ((n=0;n<${#arr[@]};n++));do
res=$(grep -Eo "[[:alnum:]._-]+</${arr[$n]}>" <<< "$line");
ttr+="${res/<\/${arr[$n]}>/}|";
done
echo "${ttr}" >> ${arqsa}
fi
done<${arqen}

sed -i 's/|$//' ${arqsa}

Arquivo_final
NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular
AAAA|12345678900|8523690|2009-10-02|Ouvidores|2009-10-05|R|63.00|Liberado|0|25|2000-01-01|A|
BBBB|14785236900|9874561|2023-05-12|CPC-S100|2023-05-14|A|77.00|Resultado Fornecido/Liberado|0|46|2000-01-01|9999 - Instituição B|Singular 2
CCCC|78523654100||2023-05-12|CPC-S100|2023-05-14|A||Liberado|0|46|2000-01-01|1|3
DDDD|14785236900|9874561|2023-05-12||2023-05-14|A|77.00|Liberado|0|46|2000-01-01|B|4
ABCD|78523654100||2023-05-12|CPC-ABCD|2023-05-14|A||Liberado|0|46|2000-01-01|1|5
WXYZ|78523654100||||||||||||

-----------------------------------------
É isso.....


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________



Opa Marcelo, beleza?

Antes de tudo muito obrigado está realmente MUITO próximo da saída que imaginava, ficou incrível essa lógica, mas queria só tirar uma dúvida.

Percebi que nas linhas em que ele entra no else para fazer a inserção dos espaços encontrados que são vazios ele não preserva por completo os campos que tem valor, vou pegar 2 linhas do arquivo response.xml do seu exemplo:

<NomeCandidato>AAAA</NomeCandidato><CPF>12345678900</CPF><IDInscricao>8523690</IDInscricao><DataExame>2009-10-02T00:00:00</DataExame><NomeExame>Ouvidores</NomeExame><DataProcessamento>2009-10-05T15:50:15.447</DataProcessamento><SituacaoFinal>R</SituacaoFinal><GrauObtido>63.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>25</NumeroAcertos><TempoRestante>2000-01-01T01:15:46</TempoRestante><CooperativaCentral>0000 - Instituição A</CooperativaCentral>
<NomeCandidato>BBBB</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>Singular 2</CooperativaSingular>

A primeira linha falta uma coluna que é a CooperativaSingular Já na linha2 todas as colunas estão OK, com isso a saída da primeira linha do arquivo final ficou:

AAAA|12345678900|8523690|2009-10-02|Ouvidores|2009-10-05|R|63.00|Liberado|0|25|2000-01-01|A|

Se a gente comparar a coluna <StatusLiberacao> do arquivo response.xml ele tem valor = Resultado Fornecido/Liberado

Porém no arquivo final ele ficou apenas como Liberado

Na linha 2 como ela estava completa, veja que a linha preservou o nome completo dessa coluna:
BBBB|14785236900|9874561|2023-05-12|CPC-S100|2023-05-14|A|77.00|Resultado Fornecido/Liberado|0|46|2000-01-01|9999 - Instituição B|Singular 2


Outra coisa que percebi é que quando ocorre a alteração na linha qualquer string que tenha uma separação por um espaço em branco também sofre esse tipo de alteração, por exemplo:

Se a coluna <NomeCandidato> for igual a Fulano Beltrano da Silva no arquivo final fica somente Silva
Se a coluna <CooperativaCentral> for igual a Cooperativa ABC no arquivo final fica somente ABC e assim sucessivamente...

Ou seja, ele pega apenas o último valor de uma string composta.

Poderia me auxiliar com esse questão? Fiz um ajuste no seu código e acredito que assim funcione, mas espero que não tenha mudado demais a lógica do processo:

while read -r line; do
NC=$(awk -F"</[[:alpha:]]+>" '{print NF}' <<< "$line")
if (($NC == 15)); then
awk -F"</[[:alpha:]]+>" '{OFS="|"; print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}' <<< "$line" >> "${arquivo_saida}"
else
unset res ttr
for ((n = 0; n < ${#arr[@]}; n++)); do
res=$(grep -Eo "[^<>]+</${arr[$n]}>" <<< "$line")
res=${res%<\/${arr[$n]}>}
ttr+=("${res}")
done
ttr_line=$(IFS="|"; echo "${ttr[*]}")
echo "${ttr_line}" >> "${arquivo_saida}"
fi
done < "${arquivo_temp}"

sed -i -E "/^($(printf '[|]'%.0s {1.."$quantidade"}))$|^([|]{$quantidade})$/d" "${arquivo_saida}"

dos2unix "${arquivo_saida}" > /dev/null 2>&1



Mas novamente, obrigado mesmo pela ajuda esse código já foi um norte pra mim gigantesco.

Abraço!


10. Re: Transformação de XML para TXT [RESOLVIDO]

leandro peçanha scardua
leandropscardua

(usa Ubuntu)

Enviado em 09/07/2023 - 10:23h


Tem um comando chamdo xmlint que faz processamento de xml.
Eu acho que sairia mais fácil fazer um script em python para isso.


11. Re: Transformação de XML para TXT [RESOLVIDO]

Alexandre Rios
alex_tj

(usa Outra)

Enviado em 09/07/2023 - 11:57h


leandropscardua escreveu:


Tem um comando chamdo xmlint que faz processamento de xml.
Eu acho que sairia mais fácil fazer um script em python para isso.


Fala Leandro blz?

Antes de tudo vlw demais pelo apoio, na verdade o meu código original era em Python porém por limitações do ambiente corporativo da minha empresa, não foi permitido instalar as bibliotecas que eu precisava (requests e PySimpleSOAP) e por isso tive que migrar todo o código pra shell.

O Python realmente tem uma performance infinitamente melhor que o shell script para essa situação, mas não tive muitas opções quanto a isso.

De toda forma fazendo alguns testes e com a ajuda da comunidade aqui, consegui gerar os arquivos dentro do padrão estabelecido no projeto.

Obrigado e abraço!



12. Re: Transformação de XML para TXT [RESOLVIDO]

Marcelo Oliver
msoliver

(usa Debian)

Enviado em 09/07/2023 - 17:07h

alex_tj escreveu:

msoliver escreveu:

alex_tj escreveu:


msoliver escreveu:

Boa noite Alexandre.
Vamos por partes....
Com o comando:
grep -o '<ObterResultadosInicioResult>.*</ObterResultadosInicioResult>' response.xml | sed -n 's/<ObterResultadosInicioResult>\(.*\)<\/ObterResultadosInicioResult>/\1/p' 

Vc "pega" todo o arquivo, eliminando "<ObterResultadosInicioResult>" e "</ObterResultadosInicioResult>"
É isso?
----------------------------------------------------------------------------------------------------------------
Realmente, o maior problema são os campos inexistentes ....
Vejo que o ideal é padronizar o arquivo.
Sugestão:
Checar os campos a partir da var "$header"...
Fiz um teste, e o resultado foi satisfatório.
Por hora, a saída é essa:
./script.sh
-------------------------
Checar campos do Reg:1 Cmp:14
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: ok
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: not
IDInscricao: ok
DataExame: ok

Reg:00002 Campos:15 Okay
-------------------------
Checar campos do Reg:3 Cmp:13
-------------------------
NomeCandidato: ok
CPF: ok
NomeExame: ok
DataProcessamento: ok
SituacaoFinal: ok
GrauObtido: not
StatusLiberacao: ok
IDModulo: ok
NumeroAcertos: ok
TempoRestante: ok
CooperativaCentral: ok
CooperativaSingular: ok
IDInscricao: not
DataExame: ok


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________


Marcelo no XML existe uma tag que é essa: ObterResultadosInicioResult que determina o início e o fim da action, pq o SOAP ele traz várias informações na string do XML aí eu restrinjo pra pegar tudo o que está dentro disso --> <ObterResultadosInicioResult> ..... </ObterResultadosInicioResult> que é efetivamente os dados que preciso trabalhar.

E minha ideia é justamente tentar comparar linha a linha com o cabeçalho, mesmo sabendo que pode ser que isso deixe o processo lento, mas o desafio realmente é marcar o vazio na linha com o ||

Em python eu fazia isso e funcionava perfeitamente:
......
Só que em ambiente corporativo existem algumas bibliotecas que usava que não poderia ser instaladas e por isso estou migrando o código para shell script.
Obrigado pela ajuda!


Alexandre, boa noite.
Entendi sobre a 'tag' ObterResultadosInicioResult,
fiz os testes sem ela, e com um registro por linha,conforme arquivo abaixo.
"Parece" que funcionou.....
cat response.xml
<NomeCandidato>AAAA</NomeCandidato><CPF>12345678900</CPF><IDInscricao>8523690</IDInscricao><DataExame>2009-10-02T00:00:00</DataExame><NomeExame>Ouvidores</NomeExame><DataProcessamento>2009-10-05T15:50:15.447</DataProcessamento><SituacaoFinal>R</SituacaoFinal><GrauObtido>63.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>25</NumeroAcertos><TempoRestante>2000-01-01T01:15:46</TempoRestante><CooperativaCentral>0000 - Instituição A</CooperativaCentral>
<NomeCandidato>BBBB</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>Singular 2</CooperativaSingular>
<NomeCandidato>CCCC</NomeCandidato><CPF>78523654100</CPF><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>Coop 1</CooperativaCentral><CooperativaSingular>Singular 3</CooperativaSingular>
<NomeCandidato>DDDD</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>Singular 4</CooperativaSingular>
<NomeCandidato>ABCD</NomeCandidato><CPF>78523654100</CPF><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-ABCD</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>Coop 1</CooperativaCentral><CooperativaSingular>Singular 5</CooperativaSingular>
<NomeCandidato>WXYZ</NomeCandidato><CPF>78523654100</CPF>


Script:

#!/usr/bin/env bash
NR=0;
header="NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular"
arr=(${header//|/ });
arqen='response.xml';
arqsa=$(printf 'ARQUIVO_FINAL_%(%Y%m%d)T.txt');

#Llimpa arq
sed -i.bak 's/<[[:alpha:]]\+>//g;' ${arqen}

#altera formato da data:
sed -ri 's/T[0-9:.]+//g' ${arqen}

#Insere Cabeçalho
echo $header > ${arqsa};

while read line;do
NC=$(awk -F"</[[:alpha:]]+>" '{print NF}' <<< "$line");
echo "Reg:$((++NR)) Campos:$NC";
if (($NC == 15));then
awk -F"</[[:alpha:]]+>" '{OFS="|"; print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}' <<< "$line" >> ${arqsa}
else
unset res ttr;
for ((n=0;n<${#arr[@]};n++));do
res=$(grep -Eo "[[:alnum:]._-]+</${arr[$n]}>" <<< "$line");
ttr+="${res/<\/${arr[$n]}>/}|";
done
echo "${ttr}" >> ${arqsa}
fi
done<${arqen}

sed -i 's/|$//' ${arqsa}

Arquivo_final
NomeCandidato|CPF|IDInscricao|DataExame|NomeExame|DataProcessamento|SituacaoFinal|GrauObtido|StatusLiberacao|IDModulo|NumeroAcertos|TempoRestante|CooperativaCentral|CooperativaSingular
AAAA|12345678900|8523690|2009-10-02|Ouvidores|2009-10-05|R|63.00|Liberado|0|25|2000-01-01|A|
BBBB|14785236900|9874561|2023-05-12|CPC-S100|2023-05-14|A|77.00|Resultado Fornecido/Liberado|0|46|2000-01-01|9999 - Instituição B|Singular 2
CCCC|78523654100||2023-05-12|CPC-S100|2023-05-14|A||Liberado|0|46|2000-01-01|1|3
DDDD|14785236900|9874561|2023-05-12||2023-05-14|A|77.00|Liberado|0|46|2000-01-01|B|4
ABCD|78523654100||2023-05-12|CPC-ABCD|2023-05-14|A||Liberado|0|46|2000-01-01|1|5
WXYZ|78523654100||||||||||||

-----------------------------------------
É isso.....


______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________



Opa Marcelo, beleza?

Antes de tudo muito obrigado está realmente MUITO próximo da saída que imaginava, ficou incrível essa lógica, mas queria só tirar uma dúvida.

Percebi que nas linhas em que ele entra no else para fazer a inserção dos espaços encontrados que são vazios ele não preserva por completo os campos que tem valor, vou pegar 2 linhas do arquivo response.xml do seu exemplo:

<NomeCandidato>AAAA</NomeCandidato><CPF>12345678900</CPF><IDInscricao>8523690</IDInscricao><DataExame>2009-10-02T00:00:00</DataExame><NomeExame>Ouvidores</NomeExame><DataProcessamento>2009-10-05T15:50:15.447</DataProcessamento><SituacaoFinal>R</SituacaoFinal><GrauObtido>63.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>25</NumeroAcertos><TempoRestante>2000-01-01T01:15:46</TempoRestante><CooperativaCentral>0000 - Instituição A</CooperativaCentral>
<NomeCandidato>BBBB</NomeCandidato><CPF>14785236900</CPF><IDInscricao>9874561</IDInscricao><DataExame>2023-05-12T00:00:00</DataExame><NomeExame>CPC-S100</NomeExame><DataProcessamento>2023-05-14T21:52:16.367</DataProcessamento><SituacaoFinal>A</SituacaoFinal><GrauObtido>77.00</GrauObtido><StatusLiberacao>Resultado Fornecido/Liberado</StatusLiberacao><IDModulo>0</IDModulo><NumeroAcertos>46</NumeroAcertos><TempoRestante>2000-01-01T01:03:12</TempoRestante><CooperativaCentral>9999 - Instituição B</CooperativaCentral><CooperativaSingular>Singular 2</CooperativaSingular>

A primeira linha falta uma coluna que é a CooperativaSingular.
Já na linha2 todas as colunas estão OK, com isso a saída da primeira linha do arquivo final ficou:

AAAA|12345678900|8523690|2009-10-02|Ouvidores|2009-10-05|R|63.00|Liberado|0|25|2000-01-01|A|

Se a gente comparar a coluna <StatusLiberacao> do arquivo response.xml ele tem valor = Resultado Fornecido/Liberado

Porém no arquivo final ele ficou apenas como Liberado

Na linha 2 como ela estava completa, veja que a linha preservou o nome completo dessa coluna:
BBBB|14785236900|9874561|2023-05-12|CPC-S100|2023-05-14|A|77.00|Resultado Fornecido/Liberado|0|46|2000-01-01|9999 - Instituição B|Singular 2


Outra coisa que percebi é que quando ocorre a alteração na linha qualquer string que tenha uma separação por um espaço em branco também sofre esse tipo de alteração, por exemplo:

Se a coluna <NomeCandidato> for igual a Fulano Beltrano da Silva no arquivo final fica somente Silva
Se a coluna <CooperativaCentral> for igual a Cooperativa ABC no arquivo final fica somente ABC e assim sucessivamente...

Ou seja, ele pega apenas o último valor de uma string composta.

Poderia me auxiliar com esse questão?
Fiz um ajuste no seu código e acredito que assim funcione, mas espero que não tenha mudado demais a lógica do processo:

while read -r line; do
NC=$(awk -F"</[[:alpha:]]+>" '{print NF}' <<< "$line")
if (($NC == 15)); then
awk -F"</[[:alpha:]]+>" '{OFS="|"; print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}' <<< "$line" >> "${arquivo_saida}"
else
unset res ttr
for ((n = 0; n < ${#arr[@]}; n++)); do
res=$(grep -Eo "[^<>]+</${arr[$n]}>" <<< "$line")
res=${res%<\/${arr[$n]}>}
ttr+=("${res}")
done
ttr_line=$(IFS="|"; echo "${ttr[*]}")
echo "${ttr_line}" >> "${arquivo_saida}"
fi
done < "${arquivo_temp}"

sed -i -E "/^($(printf '[|]'%.0s {1.."$quantidade"}))$|^([|]{$quantidade})$/d" "${arquivo_saida}"

dos2unix "${arquivo_saida}" > /dev/null 2>&1



Mas novamente, obrigado mesmo pela ajuda esse código já foi um norte pra mim gigantesco.
Abraço!


Boa tarde Alexandre.
Obrigado pela melhor resposta....

O fato de "não pegar o valor completo do campo", ocorre devido a um pequeno "descuido" na regex do grep.
Note que não tem espaço:
res=$(grep -Eo "[[:alnum:]._-]+</${arr[$n]}>" <<< "$line"); 

Correção: Altere a linha acima, para:
res=$(grep -Eo "[[:alnum:]._/ -]+</${arr[$n]}>" <<< "$line") 

Coloquei espaço e barra.
-----------------------------------------------------------------------------------------------------------------
A sua regex funciona perfeitamente:
res=$(grep -Eo "[^<>]+</${arr[$n]}>" <<< "$line")
Só que demora um pouco mais que a minha sugestão....
Como são muitas linhas.... Faz diferença
----------------------------------------------------------------------------------------------------------------
Quanto ao seu script:
Gostei da solução com os campos no array,
nos testes tive problemas....
Estava usando ${mtz[@]}, por isso o erro....
--------------------------------------------------------------------
Deleta as linhas que tem somente "|" do arquivo_saida
sed -i -E "/^($(printf '[|]'%.0s {1.."$quantidade"}))$|^([|]{$quantidade})$/d" "${arquivo_saida}"
Não encontrei a atribuição da var "quantidade"....
Simplificando:
sed -i '/^|\+/' ${arquivo_temp}
Dessa forma evita a subshell: $(printf '[|]'%.0s {1.."$quantidade"})

Somente gera linhas com "pipes", se tiver linhas "vazias" em"${arquivo_temp},
Para evitar, elimine-as, antes de iniciar o laço while:
sed -i '/^$/' ${arquivo_temp}
-----------------------------------------------------------------------------------------------------------------
É isso...
______________________________________________________________________
Att.: Marcelo Oliver
______________________________________________________________________




01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts