-1

I must first state that I am not a champion in programming, although created a handy website using html, php, MySQL and some javascript. Clearly, JS is by far the language I am almost using as a baby !

I have a set of data in a xml file with the following structure (sorry for the bad characters encoding) :

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<markers> 
 <marker lat="50.84310" lng="4.39330" name="7.7cm Sockel Flak 16 RheinMetall" category="FlakKanonen" nation="Allemagne" typecanon="Artillerie de DCA" lieu="Bruxelles - Musée Royal de l'Armée" pays="Belgique" url="../AfficheCanonGET.php?IdCanonAffiche=170" /> 
 <marker lat="43.13810" lng="-80.26170" name="15cm sFH 13 L/14" category="SchwerenKanonen" nation="Allemagne" typecanon="Artillerie lourde" lieu="Brantford (ON) - Monument" pays="Canada" url="../AfficheCanonGET.php?IdCanonAffiche=256" />  
 <marker lat="61.00500" lng="24.45780" name="10cm K 14" category="LeichtKanonen" nation="Allemagne" typecanon="Artillerie légère" lieu="Hameenlinna - Finnish Artillery Museum" pays="Finlande" url="../AfficheCanonGET.php?IdCanonAffiche=317" />  
 <marker lat="45.88740" lng="11.04740" name="7cm M 99 GebK" category="GebirgsKanonen" nation="Autriche-Hongrie" typecanon="Artillerie de montagne" lieu="Rovereto - Museo Storico Italiano della Guerra" pays="Italie" url="../AfficheCanonGET.php?IdCanonAffiche=733" /><marker lat="-35.21550" lng="149.14510" name="13cm K 09 L/35" category="SchwerenKanonen" nation="Allemagne" typecanon="Artillerie lourde" lieu=" Mitchell, ACT - AWM reserve" pays="Australie" url="../AfficheCanonGET.php?IdCanonAffiche=1519" /> 
</markers>

This xml file is used in a javascript code for placing markers on a GoogleMap. Well it used to since the code does not work anymore since GoogleMap migrated to APIV3, without portability of the xml importing function I was using.

I managed to rewrite the map code in the new API v3 language, but I am stuck in what is probably very simple for you : Despite reading tens of similar threads, I am unable to adapt a code in javascript to transfer these xml file data in a javascript array

Here is what I am hoping to create :

marqueurCanonTest4[0] = {
  latitudeCanon: "-34.94570",
  longitudeCanon: "138.58050",
  nomCanon: "7.7cm FK 16",
  categorieCanon: "LeichtKanonen",
  nationCanon: "Allemagne",
  typeCanon: "Artillerie légère",
  lieuCanon: "Adelaide, SA  - Keswick Barracks, Army Museum of South Australia",
  paysCanon: "Australie",
  url: "../AfficheCanonGET.php?IdCanonAffiche=1"
};
marqueurCanonTest4[1] = {
  latitudeCanon: "-36.14640",
  longitudeCanon: "146.91680",
  nomCanon: "7.7cm FK 16",
  categorieCanon: "LeichtKanonen",
  nationCanon: "Turquie",
  typeCanon: "Artillerie légère",
  lieuCanon: "Bandiana, VIC - Army Museum",
  paysCanon: "Australie",
  url: "../AfficheCanonGET.php?IdCanonAffiche=2"
};

etc ...

I have tried to use XMLHttpRequest, but probably incorrectly.

What are ways of achieving my goal?

6
  • Regarding all the provided answers, are there any questions left? Commented Dec 23, 2023 at 18:49
  • Yes, I am still needing some help since the 'fetch' call created array does not seem to populate the same name array variable outside the 'fetch' section Commented Dec 25, 2023 at 12:34
  • I'm not able of debugging your code since I'm not in control of neither the fetch call nor your environment. You need to set breakpoints at the critical lines of code. But in case you know any of the intermediate results e.g. fetched xml code we can work from there. Commented Dec 25, 2023 at 12:44
  • 1/2 ... maybe you provide again the exact specification of the data-structure which is going to get consumed by whatever google service/api. What you were asking for was ... marqueurCanonTest4[0] = { latitudeCanon: "-34.94570", longitudeCanon: "138.58050", /* ... */ };and marqueurCanonTest4[1] = { latitudeCanon: "-36.14640", longitudeCanon: "146.91680", /* ... */ }; ... Commented Dec 25, 2023 at 20:30
  • 2/2 ... For the audience this looks like the first and the second data-item of an array that gets referred by the variable marqueurCanonTest4. Therefore all posted solutions did implement an approach that creates an array of data-items from a xml based data-structure. Commented Dec 25, 2023 at 20:30

3 Answers 3

1

Using Powershell

using assembly System.Xml.Linq 

$filename = 'c:\temp\test.xml'

$doc = [System.Xml.Linq.XDocument]::Load($filename)

$markers = $doc.Descendants('markers')[0]

$table = [System.Collections.ArrayList]::new()
foreach($marker in $markers.Elements())
{
  $newRow = [pscustomobject]@{}
  foreach($attribute in $marker.Attributes())
  {
     $newRow | Add-Member -NotePropertyName $attribute.Name.LocalName -NotePropertyValue $attribute.Value
  }

  $table.Add($newRow) | Out-Null
}
$table | Format-List

Results

lat       : 50.84310
lng       : 4.39330
name      : 7.7cm Sockel Flak 16 RheinMetall
category  : FlakKanonen
nation    : Allemagne
typecanon : Artillerie de DCA
lieu      : Bruxelles - Musée Royal de l'Armée
pays      : Belgique
url       : ../AfficheCanonGET.php?IdCanonAffiche=170

lat       : 43.13810
lng       : -80.26170
name      : 15cm sFH 13 L/14
category  : SchwerenKanonen
nation    : Allemagne
typecanon : Artillerie lourde
lieu      : Brantford (ON) - Monument
pays      : Canada
url       : ../AfficheCanonGET.php?IdCanonAffiche=256

lat       : 61.00500
lng       : 24.45780
name      : 10cm K 14
category  : LeichtKanonen
nation    : Allemagne
typecanon : Artillerie légère
lieu      : Hameenlinna - Finnish Artillery Museum
pays      : Finlande
url       : ../AfficheCanonGET.php?IdCanonAffiche=317

lat       : 45.88740
lng       : 11.04740
name      : 7cm M 99 GebK
category  : GebirgsKanonen
nation    : Autriche-Hongrie
typecanon : Artillerie de montagne
lieu      : Rovereto - Museo Storico Italiano della Guerra
pays      : Italie
url       : ../AfficheCanonGET.php?IdCanonAffiche=733

lat       : -35.21550
lng       : 149.14510
name      : 13cm K 09 L/35
category  : SchwerenKanonen
nation    : Allemagne
typecanon : Artillerie lourde
lieu      :  Mitchell, ACT - AWM reserve
pays      : Australie
url       : ../AfficheCanonGET.php?IdCanonAffiche=1519
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks you ! I had no Idea this could bé donne si simple
0

If I understood your problem correctly, you need to create a markers array in JavaScript from the provided XML file.

You'll need to parse the XML content and extract the necessary data. You can achieve this using the browser's DOMParser to convert the XML string into a DOM object and then traverse the nodes to extract the marker information.

Here's an example of how you can do this:

// Fetch the XML file
fetch('path/to/your/file.xml')
  .then(response => {
    // Check if the response is successful
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    // Parse the response as text
    return response.text();
  })
  .then(xmlString => {
    // Parse the XML string
    const parser = new DOMParser();
    const xmlDoc = parser.parseFromString(xmlString, 'text/xml');

    // Extract marker information
    const markers = Array.from(xmlDoc.getElementsByTagName('marker')).map(marker => ({
      lat: marker.getAttribute('lat'),
      lng: marker.getAttribute('lng'),
      name: marker.getAttribute('name'),
      category: marker.getAttribute('category'),
      nation: marker.getAttribute('nation'),
      typecanon: marker.getAttribute('typecanon'),
      lieu: marker.getAttribute('lieu'),
      pays: marker.getAttribute('pays'),
      url: marker.getAttribute('url'),
    }));

    // Output the markers array
    console.log(markers);

    // Use the 'markers' array in further processing here or within this scope
  })
  .catch(error => {
    console.error('There was a problem fetching the file:', error);
  });
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
  const mockedXmlResponse = {
    ok: true,
    text: () => new Promise(resolve => 
      resolve(
`<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<markers> 
  <marker lat="50.84310" lng="4.39330" name="7.7cm Sockel Flak 16 RheinMetall" category="FlakKanonen" nation="Allemagne" typecanon="Artillerie de DCA" lieu="Bruxelles - Musée Royal de l'Armée" pays="Belgique" url="../AfficheCanonGET.php?IdCanonAffiche=170" /> 
  <marker lat="43.13810" lng="-80.26170" name="15cm sFH 13 L/14" category="SchwerenKanonen" nation="Allemagne" typecanon="Artillerie lourde" lieu="Brantford (ON) - Monument" pays="Canada" url="../AfficheCanonGET.php?IdCanonAffiche=256" />  
  <marker lat="61.00500" lng="24.45780" name="10cm K 14" category="LeichtKanonen" nation="Allemagne" typecanon="Artillerie légère" lieu="Hameenlinna - Finnish Artillery Museum" pays="Finlande" url="../AfficheCanonGET.php?IdCanonAffiche=317" />  
  <marker lat="45.88740" lng="11.04740" name="7cm M 99 GebK" category="GebirgsKanonen" nation="Autriche-Hongrie" typecanon="Artillerie de montagne" lieu="Rovereto - Museo Storico Italiano della Guerra" pays="Italie" url="../AfficheCanonGET.php?IdCanonAffiche=733" /><marker lat="-35.21550" lng="149.14510" name="13cm K 09 L/35" category="SchwerenKanonen" nation="Allemagne" typecanon="Artillerie lourde" lieu=" Mitchell, ACT - AWM reserve" pays="Australie" url="../AfficheCanonGET.php?IdCanonAffiche=1519" /> 
</markers>`
      )
    ),
  };

  // mocking JavaScript's fetch function.
  function fetch(url) {
    console.log(`fetching ... $${ url }`);

    return new Promise(resolve =>
      setTimeout(resolve, 1500, mockedXmlResponse)
    );
  }
</script>

3 Comments

Thanks so much for the code i integrated Yesterday. Thé wanted table is correctly shown in thé console but i am stepping on a basic issue : although i declared before thé 'fetch' call a var array with thé same name as thé array created in your code, it IS not populated by the fetch result. Should i add a 'return' ?
Can you show what you are doing? It is unclear, but do you want a global variable that should hold the same array of items currently printed on the console (inside a promise)?
Sure ! I am using you code the following way. My issue is that it seems the array created inside your 'fetch' does not populate the same name array variable declared outside and used to create the markers on the map.
0

An approach needs to be based on ...

In addition one could choose to handle the asynchronous API calls by an async main function which makes use of the await operator in order to await the results of such deferred operations.

The beneath provided example code does mock both the fetch method and the method's api response in order to provide a working example of the full data-related round trip.

Choosing reduce for creating and aggregating an new data-item from each currently mapped marker-element is due to gaining flexibility in regards of changes to the XML markup.

While mapping a marker-element one would retrieve a list of all of its attribute-names via getAttributeNames. Parsing the attribute node-list into an array via spread syntax enables the iteration of all attribute-names via reduce. One then can aggregate an initially passed empty object / {}.

With every iteration step one has access to the currently processed attribute-name. Having provided an object as lookup-table allows for a fast lookup of the XML attribute-name's related property-name of the to be aggregated data-item. Thus, with each iteration step one is able of creating a new key-value pair from the correctly looked up key-name.

The solution in its entirety then looks like follows ...

const markerAttrToKeyLookup = {
  lat: 'latitudeCanon',
  lng: 'longitudeCanon',
  name: 'nomCanon',
  category: 'categorieCanon',
  nation: 'nationCanon',
  typecanon: 'typeCanon',
  lieu: 'lieuCanon',
  pays: 'paysCanon',
  url: 'url',
}

function createMarkerListFromXmlDocument(xmlDocument) {
  return [
    ...xmlDocument.querySelectorAll('marker')
  ]
  .map(markerElement => {

    return [...markerElement.getAttributeNames()]
      .reduce((markerItem, attrName) => {

        const key = markerAttrToKeyLookup[attrName];
        
        markerItem[key] = markerElement.getAttribute(attrName);

        return markerItem;

      }, {})
  });
}

async function main() {

  const response = await fetch('path/to/file.xml');
  const xmlText = await response.text();

  console.log({ xmlText });

  const xmlDocument = (new DOMParser)
    .parseFromString(xmlText, 'text/xml');

  // console.log({ xmlDocument });

  const markerList =
    createMarkerListFromXmlDocument(xmlDocument);

  console.log({ markerList });
}
main();
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
  const mockedXmlResponse = {
    ok: true,
    text: () => new Promise(resolve => 
      resolve(
`<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<markers> 
  <marker lat="50.84310" lng="4.39330" name="7.7cm Sockel Flak 16 RheinMetall" category="FlakKanonen" nation="Allemagne" typecanon="Artillerie de DCA" lieu="Bruxelles - Musée Royal de l'Armée" pays="Belgique" url="../AfficheCanonGET.php?IdCanonAffiche=170" /> 
  <marker lat="43.13810" lng="-80.26170" name="15cm sFH 13 L/14" category="SchwerenKanonen" nation="Allemagne" typecanon="Artillerie lourde" lieu="Brantford (ON) - Monument" pays="Canada" url="../AfficheCanonGET.php?IdCanonAffiche=256" />  
  <marker lat="61.00500" lng="24.45780" name="10cm K 14" category="LeichtKanonen" nation="Allemagne" typecanon="Artillerie légère" lieu="Hameenlinna - Finnish Artillery Museum" pays="Finlande" url="../AfficheCanonGET.php?IdCanonAffiche=317" />  
  <marker lat="45.88740" lng="11.04740" name="7cm M 99 GebK" category="GebirgsKanonen" nation="Autriche-Hongrie" typecanon="Artillerie de montagne" lieu="Rovereto - Museo Storico Italiano della Guerra" pays="Italie" url="../AfficheCanonGET.php?IdCanonAffiche=733" /><marker lat="-35.21550" lng="149.14510" name="13cm K 09 L/35" category="SchwerenKanonen" nation="Allemagne" typecanon="Artillerie lourde" lieu=" Mitchell, ACT - AWM reserve" pays="Australie" url="../AfficheCanonGET.php?IdCanonAffiche=1519" /> 
</markers>`
      )
    ),
  };

  // mocking JavaScript's fetch function.
  function fetch(url) {
    console.log(`fetching ... $${ url }`);

    return new Promise(resolve =>
      setTimeout(resolve, 1500, mockedXmlResponse)
    );
  }
</script>

3 Comments

Thanks you ! I will test the code in my script in the next days
@bernard1418 ... And, what is/was the outcome of your testing?
Peter, sorry for the delay answering. I have been very busy at work and could only test the solution today... I gate the correct import shown in the console.log, but I can't use the results on the map as I do not know how th 'export' the 'markerList' array in my main script in which I embedded your functon. Probably an easy fix, but I am sorry I am such a beginner to request help for this? Bernard

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.