3 Replies Latest reply on Jun 25, 2015 5:05 AM by frameexpert

    Recursive Algorithm Help

    frameexpert Level 4

      Hi Everyone. I am recursively processing an XML file using ExtendScript. I have a "level" variable so I can keep track of how deep I am in the structure. I want to detect when the level changes in either direction. I am having trouble figuring out how to use a "prevLevel" variable to keep track of the current level so I can see if it has changed. It seems to work when the level increases, but not when it decreases. Any help would be appreciated. Here is my script. It will prompt you for an XML file, which I will also post.

       

      main ();
      
      function main () {
          
          var xmlFile, xml;
          
          // Prompt the user for the XML file.
          xmlFile = File.openDialog ("Please select an xml file:","XML:*xml", false);
          if (xmlFile === null) {
              return; // User cancelled the XML dialog box.
          }
      
          xml = loadXmlFile (xmlFile);
          if (xml === 0) {
              alert ("XML file could not be loaded.");
              return;
          }
      
          processElements (xml, 1, 0);
      }
      
      function processElements (node, level, prevLevel) {
          
          var nodes = node.elements ();
          var count = nodes.length (), i;
          
          for (i = 0; i < count; i += 1) {
              $.writeln (level + " " + nodes[i].localName () + " (" + prevLevel + ")");
              prevLevel = level;
              if (nodes[i].hasComplexContent () === true) {
                  processElements (nodes[i], level + 1, prevLevel);
              }
          }
      }
      
      function loadXmlFile (xmlFile) {
          
          var xml = 0;
      
          // Open, read, and close the XML file.
          xmlFile.open("r");
          try {
              xml = new XML(xmlFile.read());
          } catch (e) {
              xmlFile.close();
              return xml;
          }
          xmlFile.close();
          return xml;
      }
      

       

      <?xml version="1.0" encoding="utf-8"?>
      <Boek>
        <CursusTitelblad href="C:\temp\Presentatie\CursusTitelblad-1\PresentGBS-StorOndh-CursusVB.xml" />
        <Inhoud />
        <Hoofdstuk>
          <Titelblad href="C:\temp\Presentatie\Hoofdstuk-1\PresentHfst-SignaalgeversVeld.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentInlSignaalgevers.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentWat zijn Signaalgevers.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentSignaalgevrOpnemer.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentType signaalgevers.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentType opnemers.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentTypen signalen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentSpecificatiesDocumentatie.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentMetenSignaalgevers-Signalen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-1\PresentPlaatsing Signaalgevers.xml" />
          <OpgTheorie href="C:\temp\Presentatie\Hoofdstuk-1\PresentOpgTh-SignaalgeversVeld.xml" />
          <OpgTechTake href="C:\temp\Presentatie\Hoofdstuk-1\PresentOpgvTT-SignVerbindingGBSVeld.xml" />
          <PraktijkOpdracht href="C:\temp\Presentatie\Hoofdstuk-1\PresentPrakOpdr-SignaalgeversVeld.xml" />
        </Hoofdstuk>
        <Hoofdstuk>
          <Titelblad href="C:\temp\Presentatie\Hoofdstuk-2\PresentHfst-UitvoerorganenVeld.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-2\PresentInlUitvoerorganen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-2\PresentSoortenUitvoerorganen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-2\PresentTypeStuursignalenUitvoerorganen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-2\PresentSpecificatiesUitvoerorganen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-2\PresentMetenSignalenUitvoerorganen.xml" />
          <OpgTheorie href="C:\temp\Presentatie\Hoofdstuk-2\PresentOpgTh-UitvoerorganenVeld.xml" />
          <PraktijkOpdracht href="C:\temp\Presentatie\Hoofdstuk-2\PresentPrakOpdr-UitvoerorganenVeld.xml" />
        </Hoofdstuk>
        <Hoofdstuk>
          <Titelblad href="C:\temp\Presentatie\Hoofdstuk-3\PresentHfst-SignaalverbindingGBS.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-3\PresentInlSignaalverbindGBS-Veld.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-3\PresentSoorten I-O-Modulen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-3\PresentVerbindingenVeldModulen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-3\PresentVerbindingenModulenOnderling.xml" />
          <OpgTheorie href="C:\temp\Presentatie\Hoofdstuk-3\PresentOpgTh-SignVerbindingGBSVeld.xml" />
          <PraktijkOpdracht href="C:\temp\Presentatie\Hoofdstuk-3\PresentPrakOpdr-SignVerbindingGBSVeld.xml" />
        </Hoofdstuk>
        <Hoofdstuk>
          <Titelblad href="C:\temp\Presentatie\Hoofdstuk-4\PresentHfst-SignaalverbindingenAansluit.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-4\PresentInlSignaalverbindingen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-4\PresentGebruikSchemaDocumentatie.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-4\PresentHoofd-Stuurstroomschema.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-4\PresentDocumentatieComponenten.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-4\PresentI-O-LijstenSchema.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-4\PresentKlemmenlijst-Rangeren.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-4\PresentMeten I-O-Signalen.xml" />
          <OpgTheorie href="C:\temp\Presentatie\Hoofdstuk-4\PresentOpgvTh-SignVerbindAansluit.xml" />
          <PraktijkOpdracht href="C:\temp\Presentatie\Hoofdstuk-4\PresentPrakOpdr-SignVerbindAansluit.xml" />
        </Hoofdstuk>
        <Hoofdstuk>
          <Titelblad href="C:\temp\Presentatie\Hoofdstuk-5\PresentHfst-CommVerbindingenGBS.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-5\PresentInlCommVerbingenGBS.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-5\PresentTypeCommVerbindingen.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-5\PresentGateways.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-5\PresentAdresbusGBS-systeem.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-5\PresentDataPackets.xml" />
          <OpgTheorie href="C:\temp\Presentatie\Hoofdstuk-5\PresentOpgTh-CommVerbindingenGBS.xml" />
          <PraktijkOpdracht href="C:\temp\Presentatie\Hoofdstuk-5\PresentPrakOpdr-CommVerbindingenGBS.xml" />
        </Hoofdstuk>
        <Hoofdstuk>
          <Titelblad href="C:\temp\Presentatie\Hoofdstuk-6\PresentHfst-GestructureerdSmido.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-6\PresentInlGestrucStorzGBS.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-6\PresentStoringsmeldingKlachtStoring.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-6\PresentStorzoekenSmido.xml" />
          <Onderwerp href="C:\temp\Presentatie\Hoofdstuk-6\PresentGBS-sysGebruikStorzoek.xml" />
        </Hoofdstuk>
      </Boek>
      

       

      The script will write the results to the JavaScript Console. Here are the results that I am getting. This is pretty much what I want, except when the level goes back, it doesn't properly display the previous level.

       

      1 CursusTitelblad (0)

      1 Inhoud (1)

      1 Hoofdstuk (1)

      2 Titelblad (1)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 OpgTheorie (2)

      2 OpgTechTake (2)

      2 PraktijkOpdracht (2)

      1 Hoofdstuk (1)

      2 Titelblad (1)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 OpgTheorie (2)

      2 PraktijkOpdracht (2)

      1 Hoofdstuk (1)

      2 Titelblad (1)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 OpgTheorie (2)

      2 PraktijkOpdracht (2)

      1 Hoofdstuk (1)

      2 Titelblad (1)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 OpgTheorie (2)

      2 PraktijkOpdracht (2)

      1 Hoofdstuk (1)

      2 Titelblad (1)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 OpgTheorie (2)

      2 PraktijkOpdracht (2)

      1 Hoofdstuk (1)

      2 Titelblad (1)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

      2 Onderwerp (2)

       

      So, for example, when it jumps back to one of the <Hoofdsuk> elements, I am seeing this:

       

      1 Hoofdstuk (1)

       

      instead of

       

      1 Hoofdstuk (2)

       

      -Rick

        • 1. Re: Recursive Algorithm Help
          frameexpert Level 4

          Here is a different way of expressing the recursive processElements function, although I am still having the same problem keeping track of the previous level.

           

          function processElements (node, level, prevLevel) {
             
              var nodes, count, i;
             
              $.writeln (level + " " + node.localName () + " (" + prevLevel + ")");
             
              nodes = node.elements ();
              count = nodes.length ();
              if (count > 0) {
                  prevLevel = level;
                  level += 1;
              }
              for (i = 0; i < count; i += 1) {
                  processElements (nodes[i], level, prevLevel);
              }   
          }
          
          • 2. Re: Recursive Algorithm Help
            JoH Level 2

            Presumably you've expected that prevLevel is handed over "by reference" during recursion, which is true for objects, but not for simple variables.

            It should work when you define prevLevel as an object:

             

            function main () {  
                  
                var xmlFile, xml;  
                  
                // Prompt the user for the XML file.  
                xmlFile = File.openDialog ("Please select an xml file:","XML:*xml", false);  
                if (xmlFile === null) {  
                    return; // User cancelled the XML dialog box.  
                }  
              
                xml = loadXmlFile (xmlFile);  
                if (xml === 0) {  
                    alert ("XML file could not be loaded.");  
                    return;  
                }  
                
                var prevLevel = { val : 0 };  // CHANGED
                processElements (xml, 1, prevLevel);  
            }  
              
            function processElements (node, level, prevLevel) {  
                  
                var nodes = node.elements ();  
                var count = nodes.length (), i;  
                  
                for (i = 0; i < count; i += 1) {  
                    $.writeln (level + " " + nodes[i].localName () + " (" + prevLevel.val + ")");  // CHANGED
                    prevLevel.val = level;    // CHANGED
                    if (nodes[i].hasComplexContent () === true) {  
                        processElements (nodes[i], level + 1, prevLevel);  
                    }  
                }  
            }  
            
            • 3. Re: Recursive Algorithm Help
              frameexpert Level 4

              Excellent! Thank you very much.