views:

75

answers:

3

For example : this is an xslt

<xsl:template match="/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node_1
|/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node_2
|/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node_3
 .
 .
|/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node_N"/>

In the above code can I use the XPath /root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4 only once [use the braces or whatever] and reduce the bulkiness of the code?

As you can see, all the nodes are siblings of each-other, so except their name their Xpath is same. Is there any short-hand property ?

Does XSLT 1.0 (or Xpath1.0) allows it?

+1  A: 

Only tested it in an online xpath tool, so not entirely sure, but it should work

<xsl:template match="/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node()[name() = 'node_1' or name()='node_2' ... or name()='node_N']"/>

If there aren't any nodes in dummy4 you want to omit, just drop the [..]

Ledhund
+3  A: 

Ask yourself if the long specific match expression is really necessary. I see that this is an example only, but you don't really have to include the complete path to the element, only as much as necessary to make it unambiguous.

Further, I remind you of the self axis:

<xsl:template match="/.../dummy4/*[self::node_1 or self::node_2 ...]" />

If the name is structured and predictable, you can do

<xsl:template match="/.../dummy4/*[substring-before(name(), '_') = 'node']" />
Tomalak
+2  A: 

Does XSLT 1.0 (or Xpath1.0) allows it?

The following is a correct XPath 1.0 expression:

root/sub-root/parent/child/grand_child
              /dummy1/dummy2/dummy3/dummy4
                /*
                 [starts-with(name(), 'node_')
                and
                  substring-after(name(), 'node_') >= 1
                and
                  not(substring-after(name(), 'node_') > $N)
                  ]

However, match patterns are only a subset of all XPath expressions and certain restrictions apply on them. In particular, in XSLT 1.0 they cannot contain a reference to an xsl:variable.

In case the value N is statically known, then one will substitute this literal value (say 1000) in the above XPath expression, and thus have a valid XSLT 1.0 match pattern.

Do note that this is an extreme case and it is extremely unlikely in any practical circumstances to need such a long match pattern. By definition, a match pattern doesn't need to specify the complete path to the node -- only a sufficient "from-right-subpath" that disambiguates the node from other nodes with the same name that must be processed by a different template.

So, in most cases even the following will be sufficient:

 *
 [starts-with(name(), 'node_')
and
  substring-after(name(), 'node_') >= 1
and
   not(substring-after(name(), 'node_') > {N})

 ]

where {N} must be replaced by a integer literal -- the actual value of $N.

Or, in the easiest case (happens quite often), if there are four nodes and no disambiguation is necessary, one would just use:

 node_1|node_2|node_3|node_4
Dimitre Novatchev
what if the node names aren't identical? I mean node_1, node_2 are just examples .. in typical example I will not be having them ..
infant programmer
@infant-programmer, then you need to have all of the possible elements' names in a separate structure, and compare the name of eac element being processed with the names from this structure. Tyoically, we are talking about having a separate "lookup file". This becomes another question, you may want to ask it. :)
Dimitre Novatchev
@Dimitre Novatchev, No no, thanks, I think I never need it, suggestion by Ledhund is meeting my necessity all the way and you clarified many things too :) thanks :)
infant programmer