1
votes

Comment parcourir des éléments HTML et remplir un objet Json?

Je parcours toutes les balises html d'un fichier html, vérifie si ces balises correspondent aux conditions, et j'essaie de composer un objet JSON d'un schéma suivant:

<h1 class="header">H1_Header</h1>
<h2 class="date">Date</h2>
<p>A.</p>
<p>B.</p>
<p>С.</p>
<p>D.</p>
<a class="source"><a href="http://">http://</a></a>
<h1 class="header">H1_Header2</h1>
<h2 class="date">Date2</h2>
<p>A2.</p>
<p>B2.</p>
<p>С2.</p>
<p>D2.</p>
<a class="source"><a href="http://2">http://2</a></a>

Mais Je voudrais créer la nouvelle entrée uniquement pour les éléments, classés "en-tête", tous les autres éléments doivent être ajoutés à l'entrée créée précédemment. Comment puis-je y parvenir?

Code actuel:

      {
        title: 'TestA'
      ,
       date: '10.10.10' },
      {
        title: 'TestB'
      ,
       date: '10.10.11' }

Le résultat est:

  {
    title: 'TestA'
  },
  { date: '10.10.10' },
  {
    title: 'TestB'
  },
  { date: '10.10.11' }

I Je voudrais que ce soit à ce stade quelque chose comme:

$('*').each((index, element) => {


  if ( $(element).hasClass( "header" ) ) {
      jsonObject.push({
          title: $(element).text()
      });
  };
  if( $(element).hasClass( "date" )) {
      jsonObject.push({
          date: $(element).text()
      });
   }

   //links.push($(element))
});
console.log(jsonObject)

UPD: Voici l'exemple de fichier HTML:

[
{    title: 'abc',    date: '10.10.10',    body: ' P tags here',    href: ''  },
{    title: 'abc',    date: '10.10.10',    body: ' P tags here',    href: ''  },
{    title: 'abc',    date: '10.10.10',    body: ' P tags here',    href: ''  }
]

Merci pour votre temps!


3 commentaires

Comment savez-vous quelles dates, etc. se rapportent à l'en-tête donné? Pouvez-vous fournir un exemple de Html ?


Le code html des éléments dont vous extrayez les informations serait utile ici.


"Comment savez-vous quelles dates, etc. se rapportent à l'en-tête donné?" C'est une bonne question. Les dates appartiennent à l'en-tête précédent. Mais la structure est plate. Donc, si nous rencontrons un en-tête - nous créons une nouvelle entrée, pour tout le reste, nous continuons à remplir celle créée précédemment. C'est comme ça que j'imagine, au moins.


4 Réponses :


0
votes
$('*').each((index, element) => {
  var obj = {};

  if ( $(element).hasClass( "header" ) ) {
    obj.title = $(element).text();
  };
  if( $(element).hasClass( "date" )) {
    obj.date = $(element).text()
   }

    jsonObject.push(obj);

});

3 commentaires

si vous souhaitez qu'il y ait toujours date et titre, vous pouvez ajouter else {obj.title = null) et sinon obj.date = null. Pour que vos objets soient cohérents


Ce serait une meilleure réponse si vous expliquiez comment le code que vous avez fourni répond à la question.


Merci beaucoup pour la réponse rapide! Malheureusement, il crée une nouvelle entrée {} pour chaque balise, de sorte que le nombre total d'entrées est bien plus important que souhaité.



0
votes

Je ne connais pas jQuery, mais avec JavaScript, vous pouvez faire quelque chose comme ça.

<ul>
  <li>
    <h2>A</h2>
    <date>1</date>
  </li>
  <li>
    <h2>B</h2>
  </li>
  <li>
    <date>3</date>
  </li>
</ul>
const arr = [];
document.querySelectorAll("li").forEach((elem) => {
  const obj = {};
  const title = elem.querySelector("h2");
  const date = elem.querySelector("date");
  if (title) obj["title"] = title.textContent;
  if (date) obj["date"] = date.textContent;
  arr.push(obj);
});
console.log(arr);


0 commentaires

1
votes

Sur la base de votre exemple Html , il semble que tout ce que vous essayez de collecter est dans un ordre linéaire, vous obtenez donc un titre, une date, un corps et un lien, puis un nouvel en-tête avec les éléments associés que vous voulez collecter, puisque cela ne semble pas avoir la complication d'avoir des choses ordonnées de manière non linéaire, vous pouvez faire quelque chose comme ce qui suit:

let jsonObject = null;
let newObject = false;
let appendParagraph = false;
let jObjects = [];

$('*').each((index, element) => {
  if ($(element).hasClass("header")) {
      //If newObject is true, push object into array
      if(newObject)
         jObjects.push(jsonObject);
      //Reset the json object variable to an empty object
      jsonObject = {};
      //Reset the paragraph append boolean
      appendParagraph  = false;
      //Set the header property
      jsonObject.header = $(element).text();
      //Set the boolean so on the next encounter of header tag the jsobObject is pushed into the array
      newObject = true;
  };

  if( $(element).hasClass( "date" )) {
      jsonObject.date = $(element).text();
  }

  if( $(element).prop("tagName") === "P") {
      //If you are storing paragraph as one string value
      //Otherwise switch the body var to an array and push instead of append
      if(!appendParagraph){ //Use boolean to know if this is the first p element of object
         jsonObject.body = $(element).text();
         appendParagraph = true; //Set boolean to true to append on next p and subsequent p elements
      } else {
         jsonObject.body += (", " + $(element).text()); //append to the body
      }

  }

  //Add the href property
  if( $(element).hasClass("source")) {
       //edit to do what you wanted here, based on your comment:
       jsonObject.link = $(element).next().html(); 
       //jsonObject.href= $(element).attr('href');
  }
});

//Push final object into array
jObjects.push(jsonObject);

console.log(jObjects);

Voici un jsfiddle pour cela: https://jsfiddle.net/Lyojx85e/

Je ne parviens pas à obtenir le texte des balises d'ancrage sur le violon (je crois parce que les balises d'ancrage imbriquées ne sont pas valides et seront analysées comme des balises d'ancrage séparées par le navigateur), mais le code fourni devrait fonctionner dans un exemple du monde réel. Si .text () ne fonctionne pas, vous pouvez le changer en .html () sur le lien, j'étais confus sur ce que vous essayez d'obtenir sur celui-ci, j'ai donc mis à jour la réponse pour obtenir l'attribut href du lien tel qu'il apparaît que c'est ce que vous voulez. Le fait est que l'ancre avec la classe n'a pas d'attribut href, donc je vous laisse le soin de corriger cette partie vous-même, mais cette réponse devrait vous donner ce dont vous avez besoin.


2 commentaires

Fonctionne splendide! Un grand merci! Et tous les commentaires - ont aidé à comprendre ce qui se passe. Pour accéder au lien, j'ai utilisé la méthode .next (). Heureusement, cheerio les soutient la plupart / tous? des méthodes Jquery. // Ajout de la propriété link if ($ (element) .hasClass ("source")) {jsonObject.link = $ (element) .next (). html (); }});


@ A.Howe Content que je puisse vous aider. Bon à savoir que vous avez un correctif pour la partie href. Bon travail.



0
votes

Utilisez toujours la carte pour des choses comme celle-ci. Cela devrait ressembler à quelque chose comme:

let objects = $('.header').get().map(el => {
  return {
    date: $(el).attr('date'),
    title: $(el).attr('title'),
  }
})


2 commentaires

"Toujours utiliser la carte" , c'est une réponse assez finie sans aucune raison de sauvegarder cette déclaration. De plus, rien dans votre réponse ne fonctionnerait avec le message du PO car les éléments header ne contiennent que le titre et non la date et vous avez omis les paragraphes et hrefs.


Utilisez la carte au lieu d'insérer des éléments dans chaque - le reste n'était qu'un exemple.