2

I have an existing xslt file that I've created before with several templates.

Now, the requirements have changed and now before processing one of these specific templates I have to check if the current evaluating node has a specific attribute or not.

If yes, another template has to be called first and then the specific one.

So basically my input XML looks like this:

<baseNode>
    <textGroup>
        <title>Title here</title>
        <text specAttr="id123456">Text here</text>
        <text>Another text</text>
    </textGroup>
    <paragraph specAttr="id123456">Other text here</paragraph>
    <references>
        <reference specAttr="id123456">
            <data title="1st Reference" ref="http://..." />
        </reference>
        <reference>
            <data title="2nd Reference" ref="http://..." />
        </reference>
        <reference specAttr="id123456">
            <data title="3rd Reference" ref="http://..." />
        </reference>
    </references>
</baseNode>

Now, parsing the XML file, the result should be something like this (actually the result contains FO-tags as I want to create a PDF via Apache FOP, this is just to simplify what I want to do):

<base>
    <title>Title here</title>
    <text>Next text has this attribute</text>
    <text>Text here</text>
    <text>Another text</text>
    <text>Next text has this attribute</text>
    <p>Other text here</p>
    <table>
        <head>
            <row>
                <cell>Title</cell>
                <cell>URL</cell>
            </row>
        </head>
        <body>
            <row>
                <cell col-span="2">
                    <text>Next text has this attribute</text>
                </cell>
            </row>
            <row>
                <cell>1st Reference</cell>
                <cell>http://...</cell>
            </row>
            <row>
                <cell>2nd Reference</cell>
                <cell>http://...</cell>
            </row>
            <row>
                <cell col-span="2">
                    <text>Next text has this attribute</text>
                </cell>
            </row>
            <row>
                <cell>3rd Reference</cell>
                <cell>http://...</cell>
            </row>
        </body>
    </table>
</base>

Well...there are several elements in the XML that can have this attribute 'specAttr' and I don't want to change each existing <xsl:template> to check for this attribute as well...

I tried to add a <xsl:template match="*"> which did that job and hoped it will match for each element before the specific template of this element is processed. But it seems as if this only works for nodes that does not a specific xsl:template defined.

I've also already read here that it is possible to create templates matching attributes with <xsl:template match="@specAttr">, but this template is only parsed if I add <xsl:apply-templates select="@*"/>. So I would also have to change each already existing template and add this line.

Is it possible to create something like a template-hierarchy or inheritance between templates? That always the parent template would be processed before the actual templat e of the current node?

Edit: Looking to the reference element you can see that I also have to know sometimes in which location I have to process the new template...If a reference has this attribute I have to create a complete new row with a column span of 2 (but sometimes in another table that could also be 4), because just adding the text node would not be enough...

Thinking about this I think there is no way to find a generic way to do this...

Or does anyone have another smart idea?

If you need more information or have questions, please don't hesitate to ask.

Thanks in advance.

BRgrds, Jens

Community
  • 1
  • 1
Jens
  • 53
  • 5
  • Could you not just add, before the applying of the general (regular) template, an ` – Aleski Aug 06 '14 at 08:39
  • Please post your existing XSLT (minimized to what's necessary to handle the given example). – michael.hor257k Aug 06 '14 at 09:08
  • @Aleski I can do this, but this way I would have to adapt each template to firstly test on the attribute before continuing, and thats basically what I want to avoid. – Jens Aug 07 '14 at 07:58
  • @michael.hor257k Well, the sample output above is extremely simplified and only to give you an idea how it would look like. Actually the output contains FO tags which are rendered to a PDF vie Apache's FOP... – Jens Aug 07 '14 at 08:00
  • http://stackoverflow.com/help/mcve – michael.hor257k Aug 07 '14 at 08:17

1 Answers1

0

The xsl:next-match instruction can be useful here (or if you're in XSLT 1.0, xsl:apply-imports). This allows you to do something like

<xsl:template match="*[@specAttr]" priority="20">
  <doSomethingSpecial>
    <xsl:next-match/>
  </doSomethingSpecial>
</xsl:template>

where the next-match instruction invokes your existing rule, ie. the rule that would have matched in the absence of this one. (apply-imports is slightly different, the second rule has to be in an imported stylesheet).

This doesn't work quite so well if you need to insert something into the middle of the output created by the overridden template rule. But it's not clear from your problem statement whether you need to do that. If you do, it can sometimes be achieved by having the overriding template rule capture the output of the overridden template rule in a variable, and then transforming the content of the variable.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • That's a nice idea. Actually almost the thing I was looking for and it would work quite well...but, trying your suggestion I was facing the problem that I could process my general template before the specific one, but actually sometimes I have to decide if I also have to add a new table-row with a column-span (that also may differ) or not...I've edited my inital post trying to explain what I mean...Maybe I have to create a more general template for some tags and another one for other tags. I can't find a good way again to create just one generic one which works in al locations... – Jens Aug 07 '14 at 08:06