Copy link to clipboard
Copied
Hi! I have a rather large document created from an XML file, and I'd like to convert a series of my XML tags to anchored text frames so I can hang them off the left edge of lines they appear in.
My XML file is laid out as
>root
>chapter
>para
>id
1
>verse
text
>id
>verse
etc... see file snippet here http://1drv.ms/1dX6lYO
So far I have the following, which gets me an array containing all the id elements.
var myDocument = app.activeDocument;
var myXMLidElement = myDocument.xmlElements.itemByName("book").xmlElements.itemByName("c").xmlElements.itemByName("p").xmlElements.itemByName("id");
var myXMLidText= (myXMLidElement.contents);
var myXMLidLength = myXMLidText.length;
for (var i = 0; i < myXMLidLength; i++) { //loop to go through
//alert (myXMLidText);
myDocument.select(myXMLidText[0]); //this gives me an error saying expected data type needs to be array. Can someone explain? Where do I find info on the select command?
myDocument.selection[0].insertionPoints[0].textFrames.add(myXMLidText[0]); //haven't managed to get to this line yet, but I want it to create an inline text frame at the point of the selected text and set the frame's contents to be my XML Id Text
I suppose I'd then want to delete all my id text too, but that's unimportant.
Some other random snippets I could use?
myInlineFrame.contents = "myXMLidText";
Any pointers on creating the inline frames and logic loop? I'm an old hand with InDesign, but new to scripting, so be gentle.
1 Correct answer
Try this,
var myDocument = app.activeDocument;
var root = myDocument.xmlElements[0];
var myXMLidElement = root.evaluateXPathExpression("//book/c/p/id");
for (var i = 0; i < myXMLidElement.length; i++)
{
myDocument.select(myXMLidElement);
var myTextframe = myXMLidElement.placeIntoInlineFrame(["1p","1p"]);
}
Copy link to clipboard
Copied
Try this,
var myDocument = app.activeDocument;
var root = myDocument.xmlElements[0];
var myXMLidElement = root.evaluateXPathExpression("//book/c/p/id");
for (var i = 0; i < myXMLidElement.length; i++)
{
myDocument.select(myXMLidElement);
var myTextframe = myXMLidElement.placeIntoInlineFrame(["1p","1p"]);
}
Copy link to clipboard
Copied
Hi Sajeev,
Thanks for the response. It doesn't seem to be doing anything yet, but that's probably because I don't understand it. Note that I've moved everything up a level, chapters now appear under the root tag as the book tag was superfluous. Here's what I think is going on and this is bound to show how limited my understanding is:
function myXMLSnippet(){
var myDocument = app.activeDocument;
var root = myDocument.xmlElements[0];//set root equal to the XML document root
var myXMLidElement = root.evaluateXPathExpression("//c/p/id"); /*set XMLidElement equal to a specific tag in the DOM.
What data type is this? Is it the name of the tag as it appears in XML or the actual text in between the <id></id> tags? How is it stored?*/
//alert (myXMLidElement);
for (var i = 0; i < myXMLidElement.length; i++) //Length is the number of these tags in the entire document?
{
myDocument.select(myXMLidElement); //does this place the cursor at the point the tag appears in my text?
var myTextframe = myXMLidElement.placeIntoInlineFrame(["1p","1p"]); //creates an inline text frame within my existing text frame at that point in my text flow? What does the 1p mean?
}
}
If I'm completely wrong, please explain. If I'm just mostly wrong, also please explain. This is a huge help! I can't believe I got a response.
Regards,
Andrew
Copy link to clipboard
Copied
Hi Andrew,
Please find my response below:
- var myXMLidElement = root.evaluateXPathExpression("//c/p/id"); /*set XMLidElement equal to a specific tag in the DOM.
- What data type is this? Is it the name of the tag as it appears in XML or the actual text in between the <id></id> tags? How is it stored?*/
- //alert (myXMLidElement);
Evaluates an XPath expression starting at this XML element in the structure, it stores all the properties like tag name, tag contents etc.
- You need tag name means you have to code like myXMLidElement.markupTag.name
- you need contents of the tag means - myXMLidElement.contents
- for (var i = 0; i < myXMLidElement.length; i++) //Length is the number of these tags in the entire document?
Number of tags (i.e., for your case "id" tags) appears in the entire document
myDocument.select(myXMLidElement);
Nope this will select the XML tag (for your case "id" tags) in the document
var myTextframe = myXMLidElement.placeIntoInlineFrame(["1p","1p"]);
This line will create inline frame in your existing textframe and "1p" (1 pica) means size of your inline text frame (you can change the size as per your requirements)
HTH
Copy link to clipboard
Copied
Thanks Sajeev,
You were extraordinarily correct, and your explanations really helped. Thanks a heap!
Regards,
Andrew
Copy link to clipboard
Copied
>> Note that I've moved everything up a level, chapters now appear under the root tag as the book tag was superfluous.
I don't clearly understand, what you've moved to where. Your sample XML file (that you've linked to) looked all right. If I import it, »root« becomes »book«. You need a root XML element. In your case it's »book«. After XML import, your structure pane looks like this:
I've tested Sajeev Sridharan's code (in CS6) and got the following result (all inline frames marked in magenta):
So the code works fine. Please clarify your problem (screenshots, sample documents ...).
Tobias
Copy link to clipboard
Copied
Yes, I noticed that after I uploaded. Have updated the file to have root as the root element for future testers etc.
Additionally, I've just realised what my problem was, and it was a stupid one, so I'll only say it publicly on the internet. Basically I'd wrapped it all up in a function, and it works perfectly without one. Thanks for testing in a less stupid way than me. I'm amazed at how willing you guys are to help out! It's fantastic!
Regards,
Andrew
Copy link to clipboard
Copied
Ah, I see! If you wrap it into a function, you have to call that function in order to get it to work like this:
myXMLSnippet();
function myXMLSnippet(){
var myDocument = app.activeDocument;
var root = myDocument.xmlElements[0];//set root equal to the XML document root
var myXMLidElement = root.evaluateXPathExpression("//c/p/id"); /*set XMLidElement equal to a specific tag in the DOM.
What data type is this? Is it the name of the tag as it appears in XML or the actual text in between the <id></id> tags? How is it stored?*/
//alert (myXMLidElement);
for (var i = 0; i < myXMLidElement.length; i++) //Length is the number of these tags in the entire document?
{
myDocument.select(myXMLidElement); //does this place the cursor at the point the tag appears in my text?
var myTextframe = myXMLidElement.placeIntoInlineFrame(["1p","1p"]); //creates an inline text frame within my existing text frame at that point in my text flow? What does the 1p mean?
}
}
I'd encourage you to add support of an object style for your ID inline frames so you can change their behavior easily. Set up an object style (in my following example I named it »name_of_object_style«) in your document before running the script:
var myDocument = app.activeDocument;
var root = myDocument.xmlElements[0];
var myXMLidElement = root.evaluateXPathExpression("//c/p/id");
for (var i = 0; i < myXMLidElement.length; i++)
{
myDocument.select(myXMLidElement);
var myTextframe = myXMLidElement.placeIntoInlineFrame(["1p","1p"]);
myTextframe.appliedObjectStyle = myDocument.objectStyles.item("name_of_object_style");
}
Tobias
Copy link to clipboard
Copied
Thanks Tobias, I was trying to figure this out from the AnchoredFrame.jsx file in the InDesign SDK, that seems pretty convoluted. Your scripts are a lot easier to comprehend, and the object style is a great addition. I had figured out I could select all the frames and change their anchored object options in the script, but an object style saves me a bunch of code and lets me update it live so +1 for dynamicism.
Copy link to clipboard
Copied
Even if you're hard coding all object/paragraph/character/cell/table options into your script: Always do it by defining a style, so after the script run your user keeps as much freedom of choices as possible.
Tobias

