Skip to main content
Inspiring
January 3, 2013
Question

XML Rule + JS example: group elements under new parents

  • January 3, 2013
  • 1 reply
  • 4221 views

Thanks again to everyone here for helping me get started! I'm now making real progress. In token of my appreciation, here's something that hopefully will eventually help others.

I've worked out how to use the XML Rule facility (together w/ some JS management) to collect groups of XML elements and create new parent elements containing each group.

The sample code here demonstrates several things in both JavaScript and InDesign Script, including:

  • Use of the XML Rules facility to quickly retrieve data from the XML structure
  • Use of the following-sibling XPath facility to obtain same-level XML elements
  • Creating XML tags, parent elements, and moving elements
  • Multi-dimensional JS array for managing XML elements

By the way, here are a few more things that were not obvious to this noob (I'm sure they are documented; just took time to find them...)

  • In the InDesign script editor, you can bring up the Object Model Viewer by pressing F1
  • In the object model viewer, you must click below "Browser" and select the InDesign Object Model before doing a search
  • At the following link is a list of links to incredibly valuable documents and a huge collection of "Scripting Guide" sample scripts. http://www.adobe.com/products/indesign/indepth.displayTab2.html#Scriptingresources
  • Using try { xyzzy; } catch (myErr) { alert(myErr); }  ... is your friend

Below is a description of what my sample code actually accomplishes. But first, here are some things I learned about the XML Rules facility. Probably obvious to someone who has used this before but hey, I'm new to this:

  1. You create a set of XML Rules and pass them to the "glue code." Each time the set of rules is run, a single (potentially complex) traversal is made through the XML Structure.
  2. The implication of #1 is that for any given element in the structure, the first rule that matches the element will process it. Thus, the sequence of rule definitions is always important. This both simplifies and sometimes makes more complex how one designs a set of rules.
  3. An example in my case:
    • I wanted to collect all elements at one level into "groups", with a particular (known) tag as the first element in each group.
    • It was pretty clear how to find the known tag; use an XPath like "/devices/name" if the tag is "name" underneath "/devices."
    • But how to collect the intervening tags? In normal XPath/XSLT syntax, this is a bit complicated. But in the XML Rule system, it's actually easy...
    • Since the first rule will always collect every "name" element, my second rule becomes simply "/devices/name/following-sibling::*" which means "collect all siblings after the 'name' element. Normally, that would include following name elements as well, but it does not do so here since the first rule collects those.
  4. Don't bother trying to rearrange the XML structure from within XML Rule processing. In certain limited situations it can work... but it is just as easy, and quite reliable, to collect the needed info during XML Rule processing, then make the structure changes as a later step.

The MakeXMLGroups(myXPath,myParentTag,myHeadTag) function changes:

Devices

   Name

   Type

   Desc

   Name

   Quantity

   Type

   Desc

   Name

   Desc

To:

Devices

  Device

      Name

      Type

      Desc

  Device

      Name

      Quantity

      Type

      Desc

  Device

       Name

      Desc

In this case, the function call was MakeXMLGroups("/Devices","Device","Name").

(NOTE: I'm on personal travel this week so may not get back to answer questions until next week...)

Here are links to the necessary files:

http://ds.org/files/adobe/MakeXMLGroups.jsx

http://ds.org/files/adobe/grpXMLRulesExampleSetup.jsx

http://ds.org/files/adobe/grpXMLRulesExampleData.xml

Message was edited by: SLTyPete to insert file links

This topic has been closed for replies.

1 reply

John Hawkinson
Inspiring
January 3, 2013

You can paste code using the Advanced Editor under >>.

I'm sorry I haven't been around the forum much lately.

If I had been, when you asked about XML Rules, I would have given you my "standard" reply:


I would strongly discourage using the XML Rules logic in InDesign. It's very confusing to code, and while it has a template-based paradigm that might be familiar to those familiar with XSLT, it is pretty cumbersome to use. In my view, the sample code is also pretty problematic, because they don't show you how to parameterize it, and they depend a lot on code repitition.

I'd encourage you to look at my example from Re: How to shift content with in cell in xml rules table (reply #20).

SLTyPeteAuthor
Inspiring
January 3, 2013

Hi John,

1) I like that the new model adds parameterization. It's cleaner than pulling in parameters from pre-set variables. However, the given example didn't actually make much use of it. The only non-constant parameter multiply-used in the example is the "table" variable. Seems like a lot of work for not a lot of gain, at least in this case?

2) I am cautious that this new template/model condenses the paradigm sooo much, that it is no longer clear where XPath is involved vs straight constant tag names. Yes, Adobe's example is overly-expanded but that's common in code meant to be a demonstration.

3) I also am cautious that the example intermingles direct node creation into the XPath search/processing chain. I've learned to be VERY careful with this. It only can work when the changes made do not interfere with the rule processing. In my model, I simply avoid it completely (by not making node-position or node-add/remove/move changes until after tree parsing is complete.) This will always be a safe model.

Bottom line: while I very much appreciate the parameterization and lintability (is that a word? Sure makes sense to me )... I think I would still define each rule separately rather than bring them all together as an inline array in the rule processing call. To me it seems sooo condensed that the XPath meaning can become lost. (Would someone recognize that //para/section-head is actually an XPath statement that could (in another situation) be //para/* or //para/following-siblings::* ... while some of the other strings are exact-match tag names?)

I realize this is all a matter of style... my preference: clarity for the future reader, particularly when the future reader is me a year later who forgot what all those parameters and embedded methods were all about ...

Blessings,

Pete

John Hawkinson
Inspiring
January 4, 2013
1) I like that the new model adds parameterization. It's cleaner than pulling in parameters from pre-set variables. However, the given example didn't actually make much use of it. The only non-constant parameter multiply-used in the example is the "table" variable. Seems like a lot of work for not a lot of gain, at least in this case?

Well, to each his own. But to me, it's paving the way for future use.

2) I am cautious that this new template/model condenses the paradigm sooo much, that it is no longer clear where XPath is involved vs straight constant tag names. Yes, Adobe's example is overly-expanded but that's common in code meant to be a demonstration.

Well, I think you've gotta keep track of what the type of parameters are.

I don't view there being a requirement to have the type of parameters obvious from looking inside them and not at their context.

. (Would someone recognize that //para/section-head is actually an XPath statement that could (in another situation) be //para/* or //para/following-siblings::* ... while some of the other strings are exact-match tag names?)

I'd sure think so -- what else would //foobar? But regardless, I don't think that sort of thng needs to be obvious at all.

Anyhow, have fun!