16 Replies Latest reply on Jan 12, 2009 11:51 AM by (Olav_Kvern)

    Changing Values in XML tags

      Hi, I'm completely new to Scripting, but I need a script that does the following:

      Find an XML tag and Replaces its content.

      My Structure in Indesign is looking like this:

      Root
      Product
      PRD_TITLE
      PRD_TEXT
      ART_NO
      ART_PRICE

      ...with several product nodes.

      I Want to replace the content of ART_PRICE from whatever is in the element to "0:0". So that every price i zeroed.

      Please help!

      By the way I started a script something like this

      app.activeDocument.search('^9^9:^9^9',false,false,'0:0');
      app.activeDocument.search('^9^9:-',false,false,'0:0');

      But I'm thinking this is the wrong way to go when using XML elements..??

      /Mossman
        • 1. Re: Changing Values in XML tags
          I assume you are using JavaScript, but what version of InDesign are you using?

          This bit will work in CS2 and CS3:

          var products = app.activeDocument.xmlElements[0].xmlElements;
          //loop through every product
          for (var i = 0; i < products.length; i++) {
            products[i].xmlElements.item("ART_PRICE").contents = "0:0";
          }


          This script assumes that each product contains a ART_PRICE element.
          • 2. Re: Changing Values in XML tags
            srakete Level 1
            Hi Stefan,
            you could use search and replace if your xml is placed in a textframe on the page.
            If you are using CS3, this would be a perfect task for XML-Rules:

            function ResetPrice(){
            this.name = "ResetPrice";
            this.xpath = "//Root/Product/ART_PRICE";
            this.apply = function(myElement, myRuleProcessor){
            myElement.contents = "0.0";

            }
            }

            Hope this helps

            Stefan
            • 3. Re: Changing Values in XML tags
              Level 1
              Thanks KvD anD Stefan!

              KvD: Unfortunately I have products not containing ART_PRICE.

              Stefan:

              This looks interesting, but when I try to run the function like this:

              app.activeDocument.search('^9^9:^9^9',false,false,ResetPrice);

              It says app.activeDocument.Search is not a function, this is probably beacuse I have to use CS3 script style.
              The function app.activeDocument.search only works in CS2 or if i put the script in a "Version 4.0 scripts" folder, but then your function does not work...

              How do I search in CS3?

              Thanks

              /Mossman
              • 4. Re: Changing Values in XML tags
                Level 1
                Ahh! think I Solved it!!

                var products = app.activeDocument.xmlElements[0].xmlElements;
                //loop through every product
                for (var i = 0; i < products.length; i++) {

                if (products[i].xmlElements.item('ART_PRICE') !=null) {

                products[i].xmlElements.item('ART_PRICE').contents = "0:0";

                }
                else {}

                }

                Thanks both of you!

                By the way, does it look right? It seem to work ok!
                • 5. Re: Changing Values in XML tags
                  Peter Kahrel Adobe Community Professional & MVP
                  You don't need a loop for this:
                  product = app.activeDocument.xmlElements[0].xmlElements.item ('Product');
                  
                  product.xmlElements.item ('ART_PRICE').contents = '0.0';


                  works fine on your example (though you'll not see the effect until you collapse and expand the XML tree).

                  Peter
                  • 6. Re: Changing Values in XML tags
                    Level 1
                    Thanks Peter!

                    It doesnt seem to work in tables...

                    I have a table like this:

                    Name Art Price
                    aaa 11-111 100
                    bbb 22-222 50

                    The cells under Price is tagged as ART_PRICE

                    I assume this is because of the XML tree looks like this when there is a table:

                    Root
                    Product
                    Table
                    ART_PRICE

                    How do I select the tag inside the table?

                    Sorry for my total lack of programming skills :-)

                    /Stefan
                    • 7. Re: Changing Values in XML tags
                      Peter Kahrel Adobe Community Professional & MVP
                      Maybe something like this:
                      product = app.activeDocument.xmlElements[0].xmlElements.item ('Product');
                      
                      product.xmlElements.item ('Table').xmlElements.item ('ART_PRICE').contents = '0.0';

                      But I don't really know much about XML. A better approach would be to search for any ART_PRICE tag, no matter where in the tree's hierarchy it is. All the suggestions here assume that ART_PRICE is at level three as a child of Product. I think that an approach along the lines that Stefan Rakete suggested, using XPath, is the way to go, but I don't know how that works.

                      Peter
                      • 8. Re: Changing Values in XML tags
                        Peter Kahrel Adobe Community Professional & MVP
                        Come to think of it, XML structures can be traversed just like folders with files and subfolders, topic lists with topic names and subtopics, etc. Here is a function that goes through an XML tree and changes the contents of an XML element with a certain tag:

                        change_tag (app.activeDocument, 'ART_PRICE', '0.0');
                        

                        function change_tag (doc, myTag, new_value)
                           {
                           for (var i = 0; i < doc.xmlElements.length; i++)
                              {
                              if (doc.xmlElements[i].markupTag.name == myTag)
                                 doc.xmlElements[i].contents = new_value;
                              else
                                 change_tag (doc.xmlElements[i], myTag, new_value);
                              }
                           }


                        I seem to remember reading somewhere that this is a slow method compared with XPath (which you can use from CS3) but again, I don't know how that works.

                        Peter
                        • 9. Re: Changing Values in XML tags
                          Level 1
                          Thanks Peter!!!!

                          The last script worked perfectly!!

                          Thank you VERY much!!! :-)

                          and thanks to eveyone else who helped me!

                          Now I can sleep again knowing I'll save tons of time resetting prices in Indesign with the normal search/replace.

                          //Stefan
                          • 10. Re: Changing Values in XML tags
                            The use of XML Rules along the Adobe documentation is in my opinion overcomplicated, search the sample scripts for "glue code.jsx" if you're interested in details. Apparently Stefan R omitted that glue.



                            The script below demonstrates how I use the XML Rules.

                            Here the double slash works as wildcard in depth.

                            For details on xpath, see http://www.w3.org/TR/xpath



                            #target "InDesign"

                            function main()
                            {
                                var root  = app.activeDocument.xmlElements[0];
                                var xpath = "//Product//ART_PRICE";
                                var node  = null;
                                try {
                                    var proc  = app.xmlRuleProcessors.add([xpath]);
                                    var match = proc.startProcessingRuleSet(root);
                                    while( match!=undefined ) {
                                        node = match.element;
                                        node.contents = "0.0";
                                        match = proc.findNextMatch();
                                    }
                                    if( node )
                                        app.select(node);
                                } catch( ex ) {
                                    alert(ex);
                                } finally {
                                    proc.endProcessingRuleSet();
                                    proc.remove();
                                }
                            }

                            main();
                            • 11. Re: Changing Values in XML tags
                              Peter Kahrel Adobe Community Professional & MVP
                              Thanks Dirk, that code is much faster than what I had. Just for interest's sake, what errors could you possibly catch?

                              Peter
                              • 12. Re: Changing Values in XML tags
                                Level 1
                                The errors could be
                                - within the xpath (unsupported functions etc.),
                                - in the results (you could find XML attributes etc. where you expect XML elements),
                                - in other manipulating code.
                                The error handling just ensures the rule processor is released, as it is bound to the application rather than to the script session.

                                This is extracted from a larger script that I wrote in the earliest days of CS3 - a find-change style dialog to demonstrate XPath features, where the relevant variables were exposed by UI, and the functionality (that line setting the contents) had also several alternatives.

                                As I have some spare time now, I plan to revive this script and publish it on my web site.

                                Dirk
                                • 13. Re: Changing Values in XML tags
                                  i like to use a little function like this that allows for tree traversals on Indesign DOM, the only thing you would have to do is write a javascript line like so. Overly complex but this function has saved my alot of time recreating the wheel.

                                  //Set invocation
                                  invokeFunctionOnNode(parentNode,function(node)
                                  {
                                  if(node.markupTag.name == "ART_PRICE")
                                  {
                                  node.contents = "0.0";
                                  }
                                  });

                                  /*
                                  =================================================
                                  function recurses each node in the DOM and calls the anonymous method
                                  function should have a single value of the node
                                  =================================================
                                  */
                                  function invokeFunctionOnNode(parentNode, func) {
                                  var pNode = parentNode;
                                  //Call on Parent Node
                                  func(pNode);
                                  var elementCount = 0;
                                  try{
                                  elementCount = pNode.xmlElements.length;
                                  }catch(ex){}
                                  if (elementCount > 0) {
                                  var ctr = 0;
                                  for (var elem = 0 ; elem < elementCount; elem++) {
                                  var currentNode = pNode.xmlElements.item(elem);
                                  func(currentNode);
                                  try {
                                  if (currentNode.xmlElements.length > 0) {
                                  invokeFunctionOnNode(currentNode, func) ;
                                  }
                                  } catch(ex) {}
                                  }
                                  }
                                  }
                                  • 14. Re: Changing Values in XML tags
                                    (venkatesan)
                                    HI!!

                                    If There is any Option or third party Plugins to find the XML Tag in Indesign. My XML Structure is Like this

                                    Chapter
                                    Section
                                    para
                                    italic

                                    How could i find the XML Tag (Section) in indesign

                                    regards,
                                    C.K.Venkatesan
                                    • 15. Re: Changing Values in XML tags
                                      Level 1
                                      XmlRules is optimized for this type of processing. The recursive approach works fine for small documents but when using large documents suffers dramatically.

                                      Here is a sample rule that selects all sections elements and title elements from a proposed book content. It just pumps them into an array. You can modify the getArticleSections in conjuction with the xpath variable to grab the information you want.

                                      var xpath = ["//article_root/article_section","//article_root/article_title"];
                                      var articleSections = getArticleSections(xpath);
                                      //At this point, myXMLMatches contains all of the XML elements
                                      //that matched the XPath expression provided in myXPath.
                                      function getArticleSections(myXPath){
                                      var myXMLElements = new Array;
                                      var myRuleProcessor = app.xmlRuleProcessors.add(myXPath);
                                      try{
                                      var myMatchData = myRuleProcessor.startProcessingRuleSet(app.documents.
                                      item(0).xmlElements.item(0));
                                      while(myMatchData != undefined){
                                      var myElement = myMatchData.element;
                                      myXMLElements.push(myElement);
                                      myMatchData = myRuleProcessor.findNextMatch();
                                      }
                                      myRuleProcessor.endProcessingRuleSet();
                                      myRuleProcessor.remove();
                                      return myXMLElements;
                                      }
                                      catch (myError){
                                      myRuleProcessor.endProcessingRuleSet();
                                      myRuleProcessor.remove();
                                      throw myError;
                                      }
                                      }
                                      • 16. Re: Changing Values in XML tags
                                        Level 1
                                        Fellow Scripters,

                                        If you're using CS4, there's a nice method for doing this--here it is, straight from the Object Model Viewer:

                                        XMLElement.evaluateXPathExpression (using: string , prefixMappingTable:Array of any):Array of XMLItem
                                        Adobe InDesign CS4 (6.0) Object Model
                                        Evaluates an XPath expression starting at this XML element in the structure.
                                        using: Data Type: string
                                        The XPath expression.
                                        prefixMappingTable: Data Type: Array of any
                                        The namespace mapping table. Can accept: Array of Arrays of 2 Strings. (Optional)

                                        There's no need to create an XML rule to do it, as we had to do in CS3.

                                        Thanks,

                                        Ole