Hussein said:

>I don't want to show off but what you need to do can be done much simply
>by using the full power of XPath.

You can show off as much as you like - I need all the help I can get :)

I've noticed that nobody else seems to need much help writing macros. I
don't know whether this indicates that:

- nobody else is writing complex macros, or
- lots of people are writing them, but they are all smarter than me.

It seems to me that that the threshold for writing macros is quite high: the
mechanisms for handling conditions and passing parameters are unusual, and
even when using the console functionality, you don't get a lot of feedback.
I do a fair amount of XSL coding, but even so I don't find it easy using the
XPath functionality in XXE.

I'm not proposing any changes to the macro functionality - I know that there
are a lot of performance-related constraints involved, and I'm sure a lot of
effort has gone into it. But it occurs to me that if there are other macro
writers out there, then it might be an idea to pool our experience in the
form of some kind of "macro library" containing useful snippets and examples
of macro code.

To start the ball rolling, here is a "traverse" macro that will visit all of
an element's descendant nodes. To use it you need to:

        - define a view namespace on the root configuration element by adding:
                
xmlns:view="http://www.xmlmind.com/xmleditor/namespace/scope/view";
        - define two variables in the namespace ($view:current and 
$view:original)
and set them both to point to the element         whose subtree you want to
traverse
        - insert code where indicated to perform the required action on each
visited node.

  <command name="traverse">
    <macro>
      <sequence>
        <!-- an action performed on $view:current here will be performed on
every node-->
        <choice>
          <sequence>
            <match context="$view:current" pattern="node()[child::node()]"/>
            <set context="$view:current" expression="./child::node()[1]"
variable="view:current"></set>
            <command name="traverse"/>
          </sequence>
          <sequence>
            <!-- an action performed on $view:current here will only be
performed on every 'leaf' node-->
            <choice>
              <sequence>
                <match context="$view:current"
pattern="node()[following-sibling::node()]"/>
                <set context="$view:current"
expression="./following-sibling::node()[1]" variable="view:current"></set>
                <command name="traverse"/>
              </sequence>
              <sequence>
                <test context="$view:current"
expression="not(parent::node()=$view:original)"/>
                  <choice>
                    <sequence>
                      <match context="$view:current/parent::node()"
pattern="node()[following-sibling::node()]"/>
                      <set context="$view:current/parent::node()"
expression="./following-sibling::node()[1]" variable="view:current"></set>
                      <command name="traverse"/>
                    </sequence>
                 </choice>
              </sequence>
            </choice>
          </sequence>
        </choice>
      </sequence>
    </macro>
  </command>

I haven't tested it very thoroughly, but it seems to work so far. Any
corrections/suggestions/improvements gratefully received.

Today's mail from Graham Heath suggests that there is some interest out
there. It shouldn't be too hard to make a simple "search attributes" macro
that would fill the gap until 3.0 comes along. Anybody want to do that?

Regards

Kevin Flynn
Birdstep Technology ASA
Oslo, Norway



Reply via email to