Community Tip - Stay updated on what is happening on the PTC Community by subscribing to PTC Community Announcements. X
This is probably a simple question for someone with ACL experience. I am not one of those people. I am looking to create an ACL script that would allow for an author to add "id" attributes to specific tags. As an example the elements needing IDs are <proceduralStep>. These ids would have a specific format, "stp-xxxx", where the xxxx are numbers. They do not need to be sequential.
I can do this outside the editor using XSL, but I would like to make it a function in Arbortext and make it part of the authoring process. Can anyone point me in the right direction? I know that this works as a one-by-one command:
oid_modify_attr(oid_caret(),id,"stp-0001")
How do I loop over all <proceduralStep> elements and apply a new unique number? Additionally i'd like to make a menu for this command to be called from, but at the moment i'd just like to be able to make the looping work.
Thank you in advance for any assistance.
Tom Furst
Solved! Go to Solution.
You're right, your script file defines the function but doesn't call it.
To invoke the function, type
addIDs("XXX")
on the command line (where XXX is the element name you want to modify).
If things are correct, that should do the modification. If not, then you should get some kind of error message letting you know what's going wrong.
If you prefer to trigger the function when it's loaded, you can add that line to the end of the ACL file. Then sourcing the file will define the function and then run it. The downside to this is that it would mean hard-coding the value of elementname (the XXX above).
--Clay
Hi Tom--
If you're an XSL guy, you will probably want to use the XPath functions in ACL to do this. The loop might look something like this:
function addIDs(elementname) {
local oids[], o;
xpath_nodeset(oids, "//" . elementname);
for (o in oids) {
oid_modify_attr(oids[o], "id", getNextID());
}
}
You'd have to define your getNextID() function to generate a new unique ID. If you wanted to make it more general, you could have the parameter be an arbitrary XPath expression instead of an element name. Then you'd just have to tweak the xpath_nodeset() parameters.
As for adding to a menu item, see documentation for the "menu_add" command, that should get you started. You could also map it to a keyboard shortcut with the "map" command.
--Clay
I think I understand. In this example, is 'o' an integer? If it is I am thinking I can pass that to the getNextId() function and create a string with it. This is what I have as of now (using what you provided):
function addIDs(elementname)
{
local oids[], o;
xpath_nodeset(oids, "//" . elementname);
for (o in oids)
{
oid_modify_attr(oids[o], "id", getNextID(o));
}
}
function getNextID(o)
{
if(o < 10)
{
return "stp-000" + o;
}
else if(o >= 10 && o < 100)
{
return "stp-00" + o;
}
else{
return "stp-0" + o;
}
}
I have not tested this as yet, because to be honest, I am not sure how to run the ACL file against the XML I have open in the editor right now.
Thank you,
Tom
Hi Tom--
You probably want something more "globally aware" for your getNextID() function. In the loop, "o" will be an index for the array, and yes it will be an integer. However, it will in most cases (maybe all?) be 1..n where n is the number of matching elements. So, if you already have an item with id="stp-0001", and you run your script, the first element in the list will get assigned stp-0001, creating a duplicate ID and the ensuing problems.
You will probably want to check the document for all IDs of that form in the entire document, and generate the "next" one by creating a new one that you're sure doesn't already exist.
The easiest way to run the script for a particular document is to 1) run the script that defines the function (either manually or by putting it in init.acl or editinit.acl), and then invoking it from the command line at the bottom of the editor window. If you don't see it, you might have to activate it from the Tools->Preferences dialog, on the Window panel.
--Clay
I modified some, but am not sure if it works at all. I have run the file with this command:
source C:\Users\myusername\Desktop\ps.acl
It does not produce any errors, but also not changing anything. I feel like I should be calling out the function, but not sure how to do so. Am I not correctly running the script?
You're right, your script file defines the function but doesn't call it.
To invoke the function, type
addIDs("XXX")
on the command line (where XXX is the element name you want to modify).
If things are correct, that should do the modification. If not, then you should get some kind of error message letting you know what's going wrong.
If you prefer to trigger the function when it's loaded, you can add that line to the end of the ACL file. Then sourcing the file will define the function and then run it. The downside to this is that it would mean hard-coding the value of elementname (the XXX above).
--Clay
Success! Thank you very much. Learned some stuff today, love it. This is the script that works:
function addIDs(elementname)
{
local oids[], o;
xpath_nodeset(oids, "//" . elementname);
for (o in oids)
{
local s;
if(o < 10)
{
s = "stp-000" . o;
}
else if(o >= 10 && o < 100)
{
s = "stp-00" . o;
}
else{
s = "stp-0" . o;
}
oid_modify_attr(oids[o], "id", s);
}
}
addIDs("proceduralStep");
Now to implement it into a menu. Thanks again.
Tom