Need help to convert a php script to javascript

For everything that's not in any way related to PureBasic. General chat etc...
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Need help to convert a php script to javascript

Post by tatanas »

Hi,

I've retrieved a PHP script that converts an XML file to JSON. This script is interesting because it correctly handles namespaces. I'd like to convert it to JavaScript so I can use it with Purebasic. Unfortunately, I have almost no knowledge of PHP and JavaScript, so I'm looking for help. Could someone give me a hand?

Thanks in advance.

Code: Select all

<?php

/**
 * @param string $xml XML code to convert to JSON
 * @param array $options Options of the API to change JSON output
 *
 * @return array The JSON response
 */
function xmlToArray($xml, $options = [])
{
    $defaults = [
        'namespaceRecursive' => false, // Get XML doc namespaces recursively
        'removeNamespace' => true, // Remove namespace from resulting keys
        'namespaceSeparator' => ':', // Change separator to something other than a colon
        'attributePrefix' => '', // Distinguish between attributes and nodes with the same name
        'alwaysArray' => [], // Array of XML tag names which should always become arrays
        'autoArray' => true, // Create arrays for tags which appear more than once
        'textContent' => 'text', // Key used for the text content of elements
        'autoText' => true, // Skip textContent key if node has no attributes or child nodes
        'keySearch' => false, // (Optional) search and replace on tag and attribute names
        'keyReplace' => false, // (Optional) replace values for above search values
    ];
    $options = array_merge($defaults, $options);
    $namespaces = $xml->getDocNamespaces($options['namespaceRecursive']);
    $namespaces[''] = null; // Add empty base namespace

    // Get attributes from all namespaces
    $attributesArray = [];
    foreach ($namespaces as $prefix => $namespace) {
        if ($options['removeNamespace']) {
            $prefix = '';
        }
        foreach ($xml->attributes($namespace) as $attributeName => $attribute) {
            // (Optional) replace characters in attribute name
            if ($options['keySearch']) {
                $attributeName = str_replace($options['keySearch'], $options['keyReplace'], $attributeName);
            }
            $attributeKey = $options['attributePrefix'] . ($prefix ? $prefix . $options['namespaceSeparator'] : '') . $attributeName;
            $attributesArray[$attributeKey] = (string) $attribute;
        }
    }

    // Get child nodes from all namespaces
    $tagsArray = [];
    foreach ($namespaces as $prefix => $namespace) {
        if ($options['removeNamespace']) {
            $prefix = '';
        }

        foreach ($xml->children($namespace) as $childXml) {
            // Recurse into child nodes
            $childArray = xmlToArray($childXml, $options);
            $childTagName = key($childArray);
            $childProperties = current($childArray);

            // Replace characters in tag name
            if ($options['keySearch']) {
                $childTagName = str_replace($options['keySearch'], $options['keyReplace'], $childTagName);
            }

            // Add namespace prefix, if any
            if ($prefix) {
                $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName;
            }

            if (!isset($tagsArray[$childTagName])) {
                // Only entry with this key
                // Test if tags of this type should always be arrays, no matter the element count
                $tagsArray[$childTagName] = in_array($childTagName, $options['alwaysArray'], true) || !$options['autoArray'] ? [$childProperties] : $childProperties;
            } elseif (is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName]) === range(0, count($tagsArray[$childTagName]) - 1)) {
                // Key already exists and is integer indexed array
                $tagsArray[$childTagName][] = $childProperties;
            } else {
                // Key exists so convert to integer indexed array with previous value in position 0
                $tagsArray[$childTagName] = [$tagsArray[$childTagName], $childProperties];
            }
        }
    }

    // Get text content of node
    $textContentArray = [];
    $plainText = trim((string) $xml);
    if ($plainText !== '') {
        $textContentArray[$options['textContent']] = $plainText;
    }

    // Stick it all together
    $propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || $plainText === '' ? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText;

    // Return node as array
    return [
        $xml->getName() => $propertiesArray,
    ];
}

$xml = '<GPO xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.microsoft.com/GroupPolicy/Settings">
  <Identifier>
    <Identifier xmlns="http://www.microsoft.com/GroupPolicy/Types">{BCEBAC67-B698-4724-9694-18BEF3B81917}</Identifier>
    <Domain xmlns="http://www.microsoft.com/GroupPolicy/Types">mdv.lan</Domain>
  </Identifier>
  <Name>GPO Mappage Eleves</Name>
  <IncludeComments>true</IncludeComments>
  <CreatedTime>2021-03-05T11:37:23</CreatedTime>
  <ModifiedTime>2023-09-18T12:31:13</ModifiedTime>
  <ReadTime>2024-10-09T12:41:32.6928166Z</ReadTime>
  <FilterDataAvailable>true</FilterDataAvailable>
  <Computer>
    <VersionDirectory>0</VersionDirectory>
    <VersionSysvol>0</VersionSysvol>
    <Enabled>true</Enabled>
  </Computer>
  <User>
    <VersionDirectory>62</VersionDirectory>
    <VersionSysvol>62</VersionSysvol>
    <Enabled>true</Enabled>
    <ExtensionData>
      <Extension xmlns:q1="http://www.microsoft.com/GroupPolicy/Settings/DriveMaps" xsi:type="q1:DriveMapSettings">
        <q1:DriveMapSettings clsid="{8FDDCC1A-0C3C-43cd-A6B4-71A6DF20DA8C}">
          <q1:Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" name="T:" status="T:" image="2" changed="2021-08-27 08:07:36" uid="{FCE5D214-48DD-4F86-91F2-DBEFDD9256CD}">
            <q1:GPOSettingOrder>1</q1:GPOSettingOrder>
            <q1:Properties action="U" thisDrive="SHOW" allDrives="NOCHANGE" userName="" path="\\192.168.0.1\Commun" label="Echange" persistent="0" useLetter="1" letter="T" />
            <q1:Filters />
          </q1:Drive>
          <q1:Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" name="S:" status="S:" image="2" changed="2021-08-27 08:07:29" uid="{EBE52889-52DD-4C22-830F-B5EF7BCB31B1}">
            <q1:GPOSettingOrder>2</q1:GPOSettingOrder>
            <q1:Properties action="U" thisDrive="SHOW" allDrives="NOCHANGE" userName="" path="\\192.168.0.1\Groupes" label="Groupes" persistent="0" useLetter="1" letter="S" />
            <q1:Filters />
          </q1:Drive>
          <q1:Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" name="U:" status="U:" image="2" changed="2022-06-21 11:48:53" uid="{C52EA73F-41CF-4C08-8510-199296A53FE1}">
            <q1:GPOSettingOrder>3</q1:GPOSettingOrder>
            <q1:Properties action="U" thisDrive="SHOW" allDrives="NOCHANGE" userName="" path="\\192.168.0.1\%username%" label="Perso" persistent="0" useLetter="1" letter="U" />
            <q1:Filters />
          </q1:Drive>
        </q1:DriveMapSettings>
      </Extension>
      <Name>Drive Maps</Name>
    </ExtensionData>
  </User>
  <LinksTo>
    <SOMName>mdv</SOMName>
    <SOMPath>mdv.lan</SOMPath>
    <Enabled>true</Enabled>
    <NoOverride>false</NoOverride>
  </LinksTo>
</GPO>';


$xmlObject = new SimpleXMLElement($xml);

$json = xmlToArray($xmlObject, array(
    'namespaceRecursive' => true,
    'removeNamespace' => true
));

echo json_encode($json);
You can test this code there and see the json result : https://onlinephp.io/


EDIT : a conversion to PureBasic would be wonderfull :)
Last edited by tatanas on Wed Nov 06, 2024 9:04 am, edited 1 time in total.
Windows 10 Pro x64
PureBasic 6.20 x64
JoeC4281
User
User
Posts: 32
Joined: Fri Aug 06, 2021 4:47 pm

Re: Need help to convert a php script to javascript

Post by JoeC4281 »

You can try using https://copilot.microsoft.com/ to translate the code.

Joe
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Need help to convert a php script to javascript

Post by tatanas »

I tryed with duck.ai (4 IA available) and none was able to give me a result equivalent to php.
I will try copilot.
Windows 10 Pro x64
PureBasic 6.20 x64
BarryG
Addict
Addict
Posts: 4128
Joined: Thu Apr 18, 2019 8:17 am

Re: Need help to convert a php script to javascript

Post by BarryG »

Maybe ChatGPT can convert it? Or ask in a JavaScript subreddit for an actual human to convert the PHP code for you?
Last edited by BarryG on Mon Nov 11, 2024 9:53 am, edited 1 time in total.
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Need help to convert a php script to javascript

Post by tatanas »

Thx BarryG.

I tried a new approach (more human language to explain the problem instead of giving the php code), this is the best I can obtain :

Code: Select all

function xmlToJson(xml) {
    // Crée un objet JSON
    let obj = {};

    // Si l'élément a des attributs, les ajouter à l'objet
    if (xml.attributes) {
        for (let i = 0; i < xml.attributes.length; i++) {
            const attr = xml.attributes[i];
            obj[attr.nodeName] = attr.nodeValue;
        }
    }

    // Si l'élément a des enfants
    if (xml.hasChildNodes()) {
        for (let i = 0; i < xml.childNodes.length; i++) {
            const item = xml.childNodes[i];
            const nodeName = item.nodeName;

            // Gérer les espaces de noms
            const localName = nodeName.split(':').pop(); // Récupérer le nom local sans le préfixe

            // Si c'est un élément texte
            if (item.nodeType === 3) {
                const textContent = item.nodeValue.trim();
                if (textContent) {
                    obj['#text'] = textContent;
                }
            } else {
                // Appel récursif pour les éléments enfants
                const childJson = xmlToJson(item);
                if (obj[localName]) {
                    // Si l'élément existe déjà, le convertir en tableau
                    if (!Array.isArray(obj[localName])) {
                        obj[localName] = [obj[localName]];
                    }
                    obj[localName].push(childJson);
                } else {
                    obj[localName] = childJson;
                }
            }
        }
    }

    // Simplifier les valeurs
    for (const key in obj) {
        if (typeof obj[key] === 'object' && obj[key] !== null) {
            // Si l'objet a un seul enfant qui est un texte, le convertir en valeur simple
            if (Object.keys(obj[key]).length === 1 && obj[key]['#text']) {
                obj[key] = obj[key]['#text'];
            } else if (Array.isArray(obj[key]) && obj[key].length === 1) {
                // Si c'est un tableau avec un seul élément, le convertir en objet
                obj[key] = obj[key][0];
            }
        }
    }

    return obj;
}

// Fonction principale pour convertir XML en JSON
function convertXmlStringToJson(xmlString) {
    const parser = new DOMParser();
    const xmlDoc = parser.parseFromString(xmlString, "text/xml");
    return xmlToJson(xmlDoc.documentElement);
}

// Example usage
const xmlString = `<GPO xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.microsoft.com/GroupPolicy/Settings">
  <Identifier>
    <Identifier xmlns="http://www.microsoft.com/GroupPolicy/Types">{BCEBAC67-B698-4724-9694-18BEF3B81917}</Identifier>
    <Domain xmlns="http://www.microsoft.com/GroupPolicy/Types">mdv.lan</Domain>
  </Identifier>
  <Name>GPO Mappage Eleves</Name>
  <IncludeComments>true</IncludeComments>
  <CreatedTime>2021-03-05T11:37:23</CreatedTime>
  <ModifiedTime>2023-09-18T12:31:13</ModifiedTime>
  <ReadTime>2024-10-09T12:41:32.6928166Z</ReadTime>
  <FilterDataAvailable>true</FilterDataAvailable>
  <Computer>
    <VersionDirectory>0</VersionDirectory>
    <VersionSysvol>0</VersionSysvol>
    <Enabled>true</Enabled>
  </Computer>
  <User>
    <VersionDirectory>62</VersionDirectory>
    <VersionSysvol>62</VersionSysvol>
    <Enabled>true</Enabled>
    <ExtensionData>
      <Extension xmlns:q1="http://www.microsoft.com/GroupPolicy/Settings/DriveMaps" xsi:type="q1:DriveMapSettings">
        <q1:DriveMapSettings clsid="{8FDDCC1A-0C3C-43cd-A6B4-71A6DF20DA8C}">
          <q1:Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" name="T:" status="T:" image="2" changed="2021-08-27 08:07:36" uid="{FCE5D214-48DD-4F86-91F2-DBEFDD9256CD}">
            <q1:GPOSettingOrder>1</q1:GPOSettingOrder>
            <q1:Properties action="U" thisDrive="SHOW" allDrives="NOCHANGE" userName="" path="\\\\172.20.143.71\\\\Commun" label="Espace Commun" persistent="0" useLetter="1" letter="T" />
            <q1:Filters />
          </q1:Drive>
          <q1:Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" name="S:" status="S:" image="2" changed="2021-08-27 08:07:29" uid="{EBE52889-52DD-4C22-830F-B5EF7BCB31B1}">
            <q1:GPOSettingOrder>2</q1:GPOSettingOrder>
            <q1:Properties action="U" thisDrive="SHOW" allDrives="NOCHANGE" userName="" path="\\\\172.20.143.71\\\\Groupes" label="Groupes Classes" persistent="0" useLetter="1" letter="S" />
            <q1:Filters />
          </q1:Drive>
          <q1:Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" name="U:" status="U:" image="2" changed="2022-06-21 11:48:53" uid="{C52EA73F-41CF-4C08-8510-199296A53FE1}">
            <q1:GPOSettingOrder>3</q1:GPOSettingOrder>
            <q1:Properties action="U" thisDrive="SHOW" allDrives="NOCHANGE" userName="" path="\\\\172.20.143.71\\\\%username%" label="Espace Perso" persistent="0" useLetter="1" letter="U" />
            <q1:Filters />
          </q1:Drive>
        </q1:DriveMapSettings>
      </Extension>
      <Name>Drive Maps</Name>
    </ExtensionData>
  </User>
  <LinksTo>
    <SOMName>mdv</SOMName>
    <SOMPath>mdv.lan</SOMPath>
    <Enabled>true</Enabled>
    <NoOverride>false</NoOverride>
  </LinksTo>
</GPO>`;

// Convertir et afficher le résultat
const jsonResult = convertXmlStringToJson(xmlString);
console.log(JSON.stringify(jsonResult, null, 2));
Not that far from the php result. The namespaces are pretty annoying...
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
Piero
Addict
Addict
Posts: 865
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Need help to convert a php script to javascript

Post by Piero »

tatanas wrote: Mon Nov 04, 2024 10:55 amhandles namespaces
Hope this may help; very succint but has some problems…

Code: Select all

// jshint esversion: 6

xml_as_string = ` Your XML file as a string here ` ;

dom = new DOMParser().parseFromString(xml_as_string, "text/xml");
json = xml2json(dom);

function xml2json(xml) {
  if (xml.children.length === 0)
    return xml.textContent.trim();
  const obj = {};
  for (let child of xml.children) {
    const name = child.nodeName;
    if (obj[name] === undefined)
      obj[name] = xml2json(child);
    else {
      if (!Array.isArray(obj[name]))
        obj[name] = [obj[name]];
      obj[name].push(xml2json(child));
    }
  }
  return obj;
}
User avatar
Piero
Addict
Addict
Posts: 865
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Need help to convert a php script to javascript

Post by Piero »

It's not very clear to me why you cannot use PB XML functions (see xml.pb) to parse your data
Post Reply