Tricky XSLT question involving variables, serializing, processinginstructions

S

Stryder

I'm translating some complex DOM code (Perl) into XSLT and have run
into a problem I haven't been able to solve. I'm working with Saxon 9
and Java 1.6.0_012. Here's what's happening.

I've got this XML (really I've got thousands of levels in a document
but this'll suffice for this question)...

<?xml version="1.0" encoding="UTF8"?>
<toplevel>
<level link-id="a6" level-type="INDEX2" level-nbr="4">
<name>LIFO inventories</name>
<applied-name>applied name</applied-name>
<xref-list>. <i>See</i>
<xref-index>
<link-to link-
ref="txcnot_indx_top_2008q1_inventories">INVENTORIES</link-to>
<link-to link-ref="dummy_linkref">DUMMY</link-to>
</xref-index>
</xref-list>
<dont-touch-me>Please</dont-touch-me>
</level>
</toplevel>

What I want to do is to make a deep copy of children of <level> up to
and not including <dont-touch-me> excluding <applied-name>, replace
<link-to link-ref=""> with <link-to-bwd link-to-frag="@link-ref"> ,
serialize it all and store it in a processing instruction. I'm able
to grab the elements, serialize them with the Saxon serialize()
extension function and put them in a processing instruction, but I
haven't been able to replace the link-to elements. Perhaps I'm going
about it all the wrong way.

Here's the XSLT I've got so far that serializes the desired elements
but doesn't translate the link-tos...

<?xml version="1.0" encoding="UTF8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0" xmlns:saxon="http://saxon.sf.net/" extension-element-
prefixes="saxon">
<xsl:eek:utput indent="yes" encoding="UTF8"/>
<xsl:eek:utput name="serializer" method="xml" indent="no" omit-xml-
declaration="yes"/>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="level">
<xsl:variable name="make_me_a_pi">
<xsl:copy-of select="node()[not(name() = 'applied-name')
and not(name() = 'dont-touch-me') and not(preceding-sibling::dont-
touch-me)]"/>
</xsl:variable>
<xsl:element name="level">
<xsl:copy-of select="@*"/>
<xsl:processing-instruction name="a_pi"><xsl:value-of
select="saxon:serialize($make_me_a_pi, 'serializer')"/></
xsl:processing-instruction>
</xsl:element>
</xsl:template>

<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>

Any help would be greatly appreciated.

Thanks

Ralph
 
M

Martin Honnen

Stryder said:
What I want to do is to make a deep copy of children of <level> up to
and not including <dont-touch-me> excluding <applied-name>, replace
<link-to link-ref=""> with <link-to-bwd link-to-frag="@link-ref"> ,
serialize it all and store it in a processing instruction.

You will to abandon the copy-of approach and instead use the identity
transformation template and add a template for transforming link-to
elements into link-to-bwd elements.
I have also use a mode to separate that approach from other templates
you might have:

<xsl:template match="level">
<xsl:variable name="make_me_a_pi">
<xsl:apply-templates select="node()[not(self::applied-name)
and not(self::dont-touch-me) and not(preceding-sibling::dont-touch-me)]"
mode="m1"/>
</xsl:variable>
<xsl:element name="level">
<xsl:copy-of select="@*"/>
<xsl:processing-instruction name="a_pi"
select="saxon:serialize($make_me_a_pi, 'serializer')"/>
</xsl:element>
</xsl:template>

<xsl:template match="@* | node()" mode="m1">
<xsl:copy>
<xsl:apply-templates select="@* | node()" mode="m1"/>
</xsl:copy>
</xsl:template>

<xsl:template match="link-to" mode="m1">
<link-to-bwd link-to-frag="{@link-ref}">
<xsl:apply-templates select="@* | node()" mode="m1"/>
</link-to-bwd>
</xsl:template>
 
S

Stryder

Stryder said:
What I want to do is to make a deep copy of children of <level> up to
and not including <dont-touch-me> excluding <applied-name>, replace
<link-to link-ref=""> with <link-to-bwd link-to-frag="@link-ref"> ,
serialize it all and store it in a processing instruction.  

You will to abandon the copy-of approach and instead use the identity
transformation template and add a template for transforming link-to
elements into link-to-bwd elements.
I have also use a mode to separate that approach from other templates
you might have:

     <xsl:template match="level">
         <xsl:variable name="make_me_a_pi">
             <xsl:apply-templates select="node()[not(self::applied-name)
and not(self::dont-touch-me) and not(preceding-sibling::dont-touch-me)]"
mode="m1"/>
         </xsl:variable>
         <xsl:element name="level">
             <xsl:copy-of select="@*"/>
             <xsl:processing-instruction name="a_pi"
select="saxon:serialize($make_me_a_pi, 'serializer')"/>
         </xsl:element>
     </xsl:template>

     <xsl:template match="@* | node()" mode="m1">
       <xsl:copy>
         <xsl:apply-templates select="@* | node()" mode="m1"/>
       </xsl:copy>
     </xsl:template>

     <xsl:template match="link-to" mode="m1">
       <link-to-bwd link-to-frag="{@link-ref}">
         <xsl:apply-templates select="@* | node()" mode="m1"/>
       </link-to-bwd>
     </xsl:template>

Very nice! Thanks so much. I'm a bit of a newbie and didn't know
about modes but now I do.

Thanks again.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top