More About Macro Syntax

Useful stuff for users and developers of the XML based dynamic publishing system "Arbortext". All information in this wiki came from posts to the Arbortext Adepters mailing list that were identified by members of that list as being extremely useful because the mailing list has moved around over the years. For more information see the group FAQ.

This forum and its sub-forums are open to the public.
Forum rules
Discussion posts to this group should be relevant to Arbortext users. Posts on other products or from vendors are welcome, so long as the post also mentions or includes Arbortext in the subject matter. General posts on dynamic publishing and posts from vendors other than PTC will be subject to higher scrutiny and should generally avoid posting here (especially if the referenced material does not mention Arbortext). Advertisement posts for other products (e.g., "check out my product as an alternative") are not welcome. This forum is for Arbortext users to communicate with other Arbortext users about working with Arbortext products.

All posts to this forum are moderated.

User avatar
liz
Posts: 355
Joined: Sun May 31, 2015 2:34 am

More About Macro Syntax

Postby liz » Mon Jun 15, 2015 5:28 pm

Answered by: Dugald Topshee
Last Updated: 2008-08-13


Question by Chris Makler


OK, I'm in trouble again.

Is there an adjustment to the s -a -m syntax so that it doesn't search within some elements? Because when I run this more than once it finds the ~Arbortext~ within the <expression> tag and does it all over again - and since <expression> tags can't accept <expression> tags, I get lots of nice beeps.

So: I'd like it do this exact thing, but to exclude <expression> tags. Any pointers?

One other question: Once it does this, I want it to insert some code at the top of the file. Specifically, before the script runs, the top of the file looks like this

Code: Select all

...
<lexicons>
<lexicon name="internationalConversions">
<term>
<term-model>mile</term-model>
<term-value>kilometer</term-value>
</term>
</lexicon>
<lexicons>
...

I would like to write a line of code that inserts

Code: Select all

<term>
<term-model>yard</term-model>
<term-value>meter</term-model>
<term>

within the <lexicon> tag, as part of this macro. This must be amazingly easy to do, but again, I can't figure out where to look for this. The closest I've found is insert_tag but that doesn't tell me how to tell it to look for the first instance of the element <lexicon> and insert it under there. I tried doing a find-replace (using the very helpful method outlined before), replacing

Code: Select all

<lexicon name="internationalConversions">

With

Code: Select all

<lexicon name="internationalConversions">
<term>
<term-model>yard</term-model>
<term-value>meter</term-model>
<term>

But it told me I was unbalanced, which is undoubtedly true.

Any help? I know this must be a hopelessly newbie question...

Chris

Dugald Topshee answers



Hi Chris,

With regards to your first question, I'm afraid there's no "except inside" flag on the substitute command so you can't write a one-line command that will "replace all 'x' with 'y' except when 'x' is inside <a>". The good news is that you can accomplish this fairly easily by writing a custom ACL function that simply loops through the find command replacing everything. Essentially instead of making all the changes globally, you execute the find command over and over again and each time you check that the text you wanted meets your conditions. To do this, you can rely on the fact that Epic's $status variable gets set to 0 when the find command is successful. It works like this:

Code: Select all

function myFindReplace($this,$that, $tag)
{
  find -nows "$this";
  # the -nows keeps the find from continuing when it gets to the end of the file
  # essential in your case to avoid an infinite loop since the replacement text
  # sometimes includes the text you are finding
  while ($main::status == 0)
  {
    if (!oid_xpath_boolean(oid_caret(),"ancestor-or-self::$tag"))
    {
      # the found text is not inside our tag
      # delete the text:
      delete_mark null;
      # add our new text inside the tag we want
      insert("<$tag>$that</$tag>");
    }
  }
}


Once you've created this function (you can actually enter it at the command line, but it's easier to put it into a separate file with an .acl extension and load it into Epic with the source command), you can call it in your macro like this:

Code: Select all

myFindReplace("old text", "new text", "Bold")

and it will find all the "old text" and replace it with "new text" inside a <Bold> tag but not if "old text" is already inside a <Bold> tag. Of course you might want to customize it to your particular needs; for instance if you want to specify an attribute you can add it to the insert() line or if in every case the text that you are replacing is the same as the original text, then you can replace the delete_mark and insert lines with the insert_tag command to wrap your text in the tag you want to add. It might take a little trial and error to get the exact result you're looking for, but you should be able to adapt this code to your specific needs.

As for your second question, the easiest way to insert a fairly large passage of text and elements in Epic is with the insert() function which inserts any text that you want including markup. You just have to put the cursor in the correct location and then use the following ACL:

Code: Select all

insert("<term><term-model>yard</term-model>\
<term-value>meter</term-model></term>");

Of course before you call the insert() function, you need to make sure that your cursor is in the correct place, but that's not difficult - especially if you want to get to the beginning of the file. Unfortunately I can't give you the exact code to use without knowing a little bit more of your content model, but if <lexicons> is the root element and you want to be just inside the first <lexicon> of that root, then this should do the trick:

Code: Select all

xpath_nodeset($nodes,"/lexicons/lexicon[1]");
goto_oid($nodes[1]);

then do your insert.

Obviously you might need to modify this depending on the content model that you have, but there are all kinds of ways to maneuver the cursor in Epic, it shouldn't be hard to find one that's appropriate for your needs.

Cheers,
Dugald

Return to “Arbortext Code Archive (adepters.org) (Public)”

Who is online

Users browsing this forum: No registered users and 7 guests