Procurando criar um feed XML a partir de uma tabela de planilhas do Google

Aug 19 2020

Procurando ajuda, por favor, estou mexendo no código a maior parte do dia e estou preso, e esta parece ser a melhor solução que encontrei até agora.

Estou tentando criar um script que criará um arquivo XML a partir de uma tabela do Google Sheet.

A folha de exemplo é assim >>https://docs.google.com/spreadsheets/d/1tSWMiXBRyhFcAmwpH5tEJiyHCB5vjlGwuHFv865-85A/edit?usp=sharing

Encontrei este exemplo de código Planilha de exportação de script do Google para arquivo XML e é 90% do que eu preciso e consegui trabalhar por meio da publicação como um aplicativo da web aqui >>https://script.google.com/macros/s/AKfycbxVcUi6dXw0D1CWfZTlwf94gAT9QjqpG__-SaCIHVFVPzftndU/exec?id=1tSWMiXBRyhFcAmwpH5tEJiyHCB5vjlGwuHFv865-85A

Agora estou preso em fazer um loop sobre os cabeçalhos e valores, pois o XML precisa ser formatado.

Também estou encontrando alguns dos valores com atributos, então estou achando complicado adicionar o xml:lang="x-default" no exemplo abaixo 10:00: 18:00

Aqui está um exemplo do que estou tentando criar

<store store-id="F123">
    <name>Store One</name>
    <address1>123 Street</address1>
    <address2></address2>
    <city>London</city>
    <postal-code>L67 9JF</postal-code>
    <phone>123 456</phone>
    <store-hours xml:lang="x-default">10AM | 6PM</store-hours>
    <custom-attribute attribute-id="freeTextTitle" xml:lang="x-default">Store Description Title</custom-attribute>
    <custom-attribute attribute-id="v3_store_open_hours_0" xml:lang="x-default">11 AM|7 PM</custom-attribute>
</store>
<store store-id="G456">
    <name>Store Two</name>
    <address1>123 Street</address1>
    <address2></address2>
    <city>Manchester</city>
    <postal-code>L67 9DS</postal-code>
    <phone>123 456</phone>
    <store-hours xml:lang="x-default">10AM | 6PM</store-hours>
    <custom-attribute attribute-id="freeTextTitle" xml:lang="x-default">Store Description Title</custom-attribute>
    <custom-attribute attribute-id="v3_store_open_hours_0" xml:lang="x-default">11 AM|7 PM</custom-attribute>
</store>

Muito Obrigado

** Adicionado mais contexto

Obrigado, ambos, na verdade estou preso na função map () do JavaScript na função doIt tentando mapear os cabeçalhos e atributos

function doGet(e) {
  var content;
  try {
    content = doIt(e);
  } catch(err) {
    content = '<error>' + (err.message || err) + '</error>';
  }
  return ContentService.createTextOutput(content).setMimeType(ContentService.MimeType.XML);
}

function doIt(e) {
  if (!e) throw 'you cannot run/debug this directly\nyou have to either call the url or mock a call';
  if (!e.parameter.id) throw '"id" parameter not informed. Please provide a spreadsheet id.';

  var values = SpreadsheetApp.openById(e.parameter.id).getSheets()[0].getRange('A1:J4').getValues();
  return '<sheet>' + values.map(function(row, i) {
    return '<row>' + row.map(function(v) {
      return '<cell>' + v + '</cell>';
    }).join('') + '</row>';
  }).join('') + '</sheet>';
}

values ​​pega todos os valores no intervalo, mas estou um pouco perdido tentando dividir os valores.

Eu fiz algumas leituras na função map () então vou tentar outra vez

Respostas

2 Tanaike Aug 19 2020 at 15:35

Como uma modificação simples, que tal a seguinte modificação?

Em seu script, <sheet>, <row>e <cell>as tags são usadas. Mas parece que estes não estão incluídos no resultado esperado. Quando você deseja usar a linha de cabeçalho da 1ª linha como cada tag, é necessário usá-los no script. Quando seu script é modificado, ele se torna o seguinte.

Roteiro modificado:

Nesta modificação, o seu doIt()foi modificado.

function doIt(e) {
  if (!e) throw 'you cannot run/debug this directly\nyou have to either call the url or mock a call';
  if (!e.parameter.id) throw '"id" parameter not informed. Please provide a spreadsheet id.';
  var values = SpreadsheetApp.openById(e.parameter.id).getSheets()[0].getRange('A1:J4').getValues();

  // I modified below script.
  var header = values.shift();
  return values.reduce((s, r) => {
    r.forEach((c, j, a) => {
      s += j == 0 ? `<${header[j]}="${c}">` : `<${header[j]}>${c}<\/${header[j].split(" ")[0]}>`;
      if (j == a.length - 1) s += `<\/${header[0].split(" ")[0]}>`;
    });
    return s;
  }, "");
}

Resultado:

Quando o script modificado acima é executado, o seguinte resultado é obtido.

<store store-id="F123">
   <name>Store One</name>
   <address1>123 Street</address1>
   <address2 />
   <city>London</city>
   <postal-code>L67 9JF</postal-code>
   <phone>123 456</phone>
   <store-hours xml:lang="x-default">10AM | 6PM</store-hours>
   <custom-attribute attribute-id="freeTextTitle" xml:lang="x-default">Store Description Title</custom-attribute>
   <custom-attribute attribute-id="v3_store_open_hours_0" xml:lang="x-default">11 AM|7 PM</custom-attribute>
</store>
<store store-id="G456">
   <name>Store Two</name>
   <address1>124 Street</address1>
   <address2 />
   <city>Manchester</city>
   <postal-code>L67 9DS</postal-code>
   <phone>124 111</phone>
   <store-hours xml:lang="x-default">9AM | 5PM</store-hours>
   <custom-attribute attribute-id="freeTextTitle" xml:lang="x-default">Store Description Title</custom-attribute>
   <custom-attribute attribute-id="v3_store_open_hours_0" xml:lang="x-default">12 AM|7 PM</custom-attribute>
</store>
<store store-id="J542">
   <name>Store Three</name>
   <address1>777 High Street</address1>
   <address2 />
   <city>Leeds</city>
   <postal-code>L7 9GG</postal-code>
   <phone>555 222</phone>
   <store-hours xml:lang="x-default">10AM | 6PM</store-hours>
   <custom-attribute attribute-id="freeTextTitle" xml:lang="x-default">Store Description Title</custom-attribute>
   <custom-attribute attribute-id="v3_store_open_hours_0" xml:lang="x-default">12 AM|7 PM</custom-attribute>
</store>

Observação:

  • Quando você usa o resultado acima como os dados xml, por exemplo, acho que é necessário incluir como <contents>{above results}</contents>. Por favor, tenha cuidado com isso. Portanto, se você deseja exportar os dados XML válidos, use o seguinte script. Neste caso, <contents>é um tag de amostra.

      function doIt(e) {
        if (!e) throw 'you cannot run/debug this directly\nyou have to either call the url or mock a call';
        if (!e.parameter.id) throw '"id" parameter not informed. Please provide a spreadsheet id.';
        var values = SpreadsheetApp.openById(e.parameter.id).getSheets()[0].getRange('A1:J4').getValues();
    
        // I modified below script.
        var header = values.shift();
        var data = values.reduce((s, r) => {
          r.forEach((c, j, a) => {
            s += j == 0 ? `<${header[j]}="${c}">` : `<${header[j]}>${c}<\/${header[j].split(" ")[0]}>`;
            if (j == a.length - 1) s += `<\/${header[0].split(" ")[0]}>`;
          });
          return s;
        }, "");
    
        return XmlService.getPrettyFormat().format(XmlService.parse(`<contents>${data}$</contents>`));
      }
    
  • Quando você modificou o script de Web Apps, reimplemente os Web Apps como nova versão. Com isso, o script mais recente é refletido nos aplicativos da Web. Por favor, tenha cuidado com isso.

  • Use este script com a ativação do V8.

Referências:

  • reduzir()
  • para cada()