SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Enthusiast TheNinthPlayer's Avatar
    Join Date
    Jan 2004
    Location
    USA
    Posts
    74
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    JavaScript - Manipulating XML

    I created a script which loads my xml file and it also saves my xml file to a persons HD using an ActiveX plugin.

    Now what I would like to do is have my script take the loaded XML file and add/remove childelements and then save it. But I want this to be done in memory that way the user doesnt have to see it.


    So here is what the load part looks like:
    Code:
    <script type="text/javascript">
      <!--
      // Loads plugins.xml
      var xmlFile = './plugins.xml';
    
      function loadXML(xmlFile) {
        var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
    
        xmlDoc.async = false;
        xmlDoc.onreadystatechange = verify(xmlDoc);
        xmlDoc.load(xmlFile);
        xmlObj = xmlDoc.documentElement;
    
        return xmlDoc;
      }
    
      function verify(xmlDoc) {
        // 0 Object is not initialized
        // 1 Loading object is loading data
        // 2 Loaded object has loaded data
        // 3 Data from object can be worked with
        // 4 Object completely initialized
    
        if (xmlDoc.readyState != 4) {
          return false;
        }
    
        return xmlDoc;
      }
    
      function getPlugins(xmlFile) {
        loadXML(xmlFile);
    
        var pluginFiles = Array();
        var nodeCount = xmlObj.childNodes.length;
    
        for( var x = 0; x < nodeCount; x++) {
          pluginFiles[x] = xmlObj.getElementsByTagName("plugin")[x].childNodes(1).text;
        }
    
        for( var x = 0; x < pluginFiles.length; x++) {
          document.write("      <script type=\"text/javascript\" src=\"./plugins/" + pluginFiles[x] + "\"></script>\n");
        }
    
        return true;
      }
    
      getPlugins(xmlFile);
       //-->
     </script>
    I imagine I should be using the 'xmlObj' I created to add and remove child nodes but I am unsure how to do this. Anyone have any suggestions?

    Once that part is complete I have a script made to save the current xmlObj to a file.

  2. #2
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    you can use the xml-dom api. eg :
    Code:
    var foobar = xmlDoc.createElement("foobar");
    foobar.setAttribute("name", "John");
    xmlDoc.documentElement.appendChild(foobar);

  3. #3
    SitePoint Enthusiast TheNinthPlayer's Avatar
    Join Date
    Jan 2004
    Location
    USA
    Posts
    74
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've been trying to use the XMLDOM methods for a few days now but I have only figured out how to remove a node. I looked at what you posted and I think I understand what I must do better but I still can add a node.

    Your code works fine but its not what I want to do. I want to create a node with no attributes that contains two child elements.

    Basicly I want to add another 'plugin' node to what I have already:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <plugins>
      <plugin>
        <name>Music</name>
        <file>music.js</file>
      </plugin>
      <plugin>
        <name>Weather</name>
        <file>weather.js</file>
      </plugin>
      <plugin>
        <name>Notes</name>
        <file>notes.js</file>
      </plugin>
    </plugins>
    Do I need to use 'appendChild'? Ive been trying to use that and keep getting an error message.

  4. #4
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The DOM consists of Nodes, witch may have childNodes. The text contained within two "tags" is also a Node, it's called a textnode.
    In your above example, the rootnode (documentElement) is a Node, with the nodeName "plugins" and the nodeType NODE_ELEMENT. This node has 3 childNodes, all with the nodeName "plugin" and nodeType NODE_ELEMENT. Each of theese has 2 childNodes. Both have nodeType NODE_ELEMENT, but the nodeName is respectively "name" and "file". Each of theese has a Node with nodeType NODE_TEXT.

    So in order to create a new "plugin" structure and add it to the existing document, you would do something like this :
    PHP Code:
    // create the <plugin> tag
    var plugin xmlDoc.createElement("plugin");
    // create the <name> tag
    var name xmlDoc.createElement("name");
    // add the <name> tag as child of <plugin>
    plugin.appendChild(name);
    // create some text
    var name_txt xmlDoc.createTextElement("Foobar");
    // add the text to the <name> tag
    name.appendChild(name_txt);
    // same thing with <file>
    var file xmlDoc.createElement("file");
    plugin.appendChild(file);
    var 
    file_txt xmlDoc.createTextElement("foobar.js");
    file.appendChild(file_txt);

    // add the <plugin> tag to the <plugins> tag
    xmlDoc.documentElement.appendChild(plugin); 
    This may seem quite formal, but it gives you great flexsibility as a programmer, and when you have grasped the above code, there isn't much more to consume, since the DOM api is relatively small.

  5. #5
    SitePoint Enthusiast TheNinthPlayer's Avatar
    Join Date
    Jan 2004
    Location
    USA
    Posts
    74
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Im still getting an error when trying your code.

    It occours on this line of code:

    // create some text
    var name_txt = xmlDoc.createTextElement("Foobar");'

    And IE gives this error message:

    Error: Object does not support this property or method.

  6. #6
    SitePoint Enthusiast TheNinthPlayer's Avatar
    Join Date
    Jan 2004
    Location
    USA
    Posts
    74
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay I found the problem. I think you meant to say '.createTextNode' instead of '.createTextElement'. After I changed it it works great now. Thank you for your help. But I do have one last question.

    After using your code it keeps appending the new nodes onto the same line. Normally I would not care about this but I plan to have it save all of this new XML onto a file and for read ability with in the file I would like to keep each element on its own line. Is there some kind of way I can create a line return?

    Here's what its outputting right now:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <plugins>
      <plugin>
        <name>Music</name>
        <file>music.js</file>
      </plugin>
      <plugin>
        <name>Weather</name>
        <file>weather.js</file>
      </plugin>
      <plugin>
        <name>Notes</name>
        <file>notes.js</file>
      </plugin>
      <plugin><name>Foo</name><file>foo.js</file></plugin></plugins>

  7. #7
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think you meant to say '.createTextNode' instead of '.createTextElement'.
    Yes, ofcause ... I was writing off my head, so I got it confused.

    After using your code it keeps appending the new nodes onto the same line.
    That's really a bug/feature of the xml-parser. You will get different results on different platforms. The markup is valid, since thoose linebreaks and identions are "just" for making it easier to read by humans.
    Unfortunately there is no simple solution to this, using MSXML (internet explorer). You will have to either run the document through a XSLT-sheet witch arranges the markup nicely, or write a custom XML-writer, that does the job.
    For the first thing (Witch requires you to mess around with XSLT, witch is probably a bit out of your league currently) is described here : http://www.azureus.com/xml/art_prettyprinting_xml.htm

    The second method is a bit more approachable, since it doesn't involve new technology, and it may have a better compatibility, since older versions of MSXML didn't cope well with XSLT. It's also slower though. If you're interested, you could take a look at the file XML_Utility.js from the Indite project : http://www.kyberfabrikken.dk/opensou...plugin.RC3.zip
    In particular the function XML_Utility.indent() witch takes xml-source (as a String) as argument, and returns it "prettyfied".


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •