cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

xref xidtype para - target parent definition

juliette.gibb1
1-Newbie

xref xidtype para - target parent definition

Hello Adepters,

I am trying to define an xrefwith a para xidtypebut I need to define that when the parent of the target destinationis a para0 it looks like Section #.# - Infoname but when the parent of the target destinationis subpara1 then it will look like Section #.#.# - Para Title. Because the parent of the subpara1 is para0 I'm not sure how to do this. Does anyone have any suggestions? I am a little lost with the xpath relationships.

<xsl:template match="xref">

<xsl:variable name="xidtype" select="translate(./@xidtype, $upper, $lower)"/>

<xsl:variable name="target" select="./@target"/>

<xsl:variable name="xrefid" select="./@xrefid"/>

<xsl:if test="@xidtype='para'">

<xsl:if test="not(ancestor::foreword)">

<xsl:choose>

<xsl:when test="ancestor::para0">

<fo:basic-link internal-destination="{@idref}"><xsl:attribute name="internal-destination"><xsl:value-of select="@xrefid"/>xsl:attribute>

<xsl:variable name="infoname" select="ancestor::book_chapter//infoname"/>

<xsl:variable name="chapnum" select="ancestor::book_chapter//@chap_num"/>

<fo:inline color="green">Section fo:inline><xsl:value-of select="$chapnum"/>.<xsl:number count="dmodule" from="book_chapter" format="1"/> - <fo:inline font-style="italic" color="blue">'<xsl:value-of select="$infoname"/>'fo:inline>

fo:basic-link>xsl:when>

<xsl:when test="ancestor::subpara1">

<fo:basic-link internal-destination="{@idref}"><xsl:attribute name="internal-destination"><xsl:value-of select="@xrefid"/>xsl:attribute>

<xsl:variable name="infoname" select="ancestor::book_chapter//infoname"/>

<xsl:variable name="chapnum" select="ancestor::book_chapter//@chap_num"/>

<fo:inline color="red">Section fo:inline><xsl:value-of select="$chapnum"/>.<xsl:number count="dmodule" from="book_chapter" format="1"/>.<xsl:number count="para0" from="dmodule" format="1"/> - <fo:inline font-style="italic" color="blue">'<xsl:value-of select="$infoname"/>'fo:inline>

fo:basic-link>xsl:when>

xsl:choose>

xsl:if>

fo:inline>

xsl:if>

xsl:if>

xsl:template>

Thank you for your help! 🙂

Cheers,

Juliette

18 REPLIES 18

Hi Juliette,



I hope it's all going well up in Brissy 🙂 I will try and make it back up
that way soon..



There is a simple mistake in your xpath. Where you are testing against
"ancestor::para0" and "ancestor::subpara1" you need to change this to
"parent::para0" and "parent::subpara1". With ancestor:: it will look "up"
the XML tree for matches as far as it can go. With parent:: it only looks
one level above (ie. at the parent level).



Hope that helps.



Cheers,

Gareth



PS. For further reading on XML technologies like Xpath and XSLT I found this
site was not too bad:

Hi Gareth,

Things are going pretty well, other than this pesky problem! How's
little James going? I bet his into all sorts of mischief! 🙂

Thanks for your help, I've tried what you suggested below but it isn't
recognising the path now at all. I've also tried parent::para0/* and
parent::subpara1/* but that doesnt' give me any joy either. Any other
suggestions?

Cheers,
Juliette

PS. Thanks for the link to the website, it will hopefully make things
easier.

When evaluating an xsl:choose, the processor will select the first
xsl:when that matches its test condition, and so to get the result you
want you simply need to put the test for ancestor::subpara1 before the
test for ancestor::para0. That way the xrefs that are inside subpara1
tags will meet the first condition but will never be tested for the
second condition, while the xrefs that are inside para0 tags but not
inside subpara1 tags will fail the first condition, but meet the second.

Try changing your original statement to this:
<xsl:choose>
<xsl:when test="ancestor::subpara1">
<fo:basic-link internal-destination="{@idref}"> ...
</fo:basic-link></xsl:when>
<xsl:when test="ancestor::para0">
<fo:basic-link internal-destination="{@idref}"> ... </fo:basic-link>
</xsl:when>
</xsl:choose>

That should do what you need.

Cheers,

Dugald

>

This has nothing to do with this specific issue, but I have seen similar
behavior to this in FOSI, where the document sequence of <att> elements
in the FOSI can change formatting.

I don't know the answer, but I think I understand the problem.

This sentence:

> > I am trying to define an xref with a para xidtype but I need to define
> > that when the parent of the target destination is a para0
>

Doesn't match what's happening here:

> > <xsl:when test="ancestor::para0">
>

Or, probably that's vice versa. Your xpath test in xsl:when is relative to
the template match = "xref" NOT the target of the link. That ancestor
matches (but parent does not) is a distraction. Both would fail to properly
resolve (unless by chance the link and the target were siblings).

Ideally (meaning making it easy to answer this e-mail) you need to store the
target type on the link itself when it is created or updated. That way, you
know the format based on a type attr that is xpath accessible on the xref
element itself.

I'm not sure how to test the "far" element's context ...

--
Paul Nagai

Hi Paul & Juliette--

Paul, I think you've hit the nail on the head here. Juliette, you are trying to check the context of the target, but your stylesheet is checking the context of the link itself.

I think you would need something like this:


<xsl:template match="xref">

<xsl:variable name="xidtype" select="translate(./@xidtype," $upper,=" $lower)&quot;="/>

<xsl:variable name="target" select="./@target"/">

<xsl:variable name="xrefid" select="./@xrefid"/">



<xsl:variable name="targetelem" select="id($target)"/">

<xsl:if test="@xidtype='para">

<xsl:if test="not(ancestor::foreword)">

<xsl:choose>



<xsl:when test="$targetelem/parent::para0">

<fo:basic-link internal-destination="{@idref}">

<xsl:attribute name="internal-destination">

<xsl:value-of select="@xrefid"/">

</xsl:attribute>

<xsl:variable name="infoname" select="ancestor::book_chapter//infoname"/">

<xsl:variable name="chapnum" select="ancestor::book_chapter//@chap_num"/">

<fo:inline color="green">Section </fo:inline>

<xsl:value-of select="$chapnum"/">.<xsl:number count="dmodule" from="book_chapter" format="1"/"> - <fo:inline font-style="italic" color="blue">'<xsl:value-of select="$infoname"/">'</fo:inline>

</fo:basic-link>

</xsl:when>

<xsl:when test="$targetelem/parent::subpara1">

<fo:basic-link internal-destination="{@idref}">

<xsl:attribute name="internal-destination">

<xsl:value-of select="@xrefid"/">

</xsl:attribute>

<xsl:variable name="infoname" select="ancestor::book_chapter//infoname"/">

<xsl:variable name="chapnum" select="ancestor::book_chapter//@chap_num"/">

<fo:inline color="red">Section </fo:inline>

<xsl:value-of select="$chapnum"/">.<xsl:number count="dmodule" from="book_chapter" format="1"/">.<xsl:number count="para0" from="dmodule" format="1"/"> - <fo:inline font-style="italic" color="blue">'<xsl:value-of select="$infoname"/">'</fo:inline>

</fo:basic-link>

</xsl:when>

</xsl:choose>

</xsl:if>

</xsl:if>

</xsl:template>

HTH

--Clay

Hi Guys,

Clay & Paul, thank you both for your help. I've incorporated all your
suggestions and it is now reading correctly except for one minor
problem, the parent/ancestor thing. It doesn't seem to recognise parent
at all, I don't get any response when I use parent::para0 but I do if I
use ancestor::para0. I am getting the information that I want (the
title) but I can't grab the target paragraphs number if I use ancestor.

Thank you for your help. 🙂

Cheers,
Juliette

Can you post your XSL again as it is now and a small snippet of the XML
containing the target?

On Mon, May 12, 2008 at 4:21 PM, Juliette Gibb <
juliette.gibb@virginblue.com.au> wrote:

> Hi Guys,
>
> Clay & Paul, thank you both for your help. I've incorporated all your
> suggestions and it is now reading correctly except for one minor problem,
> the parent/ancestor thing. It doesn't seem to recognise parent at all, I
> don't get any response when I use parent::para0 but I do if I use
> ancestor::para0. I am getting the information that I want (the title) but I
> can't grab the target paragraphs number if I use ancestor.
>
> Thank you for your help. 🙂
>
> Cheers,
> Juliette
>

Hello,

Here is a copy of the updated XSL with your suggestions incorporated
(except for the parent data which I've had to substitute with ancestor
to get it to show anything) and an example of how our XML data is
structured. Thank you for your help.

<xsl:template match="xref">

<xsl:variable name="xidtype" select="translate(./@xidtype," $upper,<br="/>$lower)"/>

<xsl:variable name="target" select="./@target"/">

<xsl:variable name="xrefid" select="./@xrefid"/">

<xsl:variable name="xreftitle" select="@title"/">

<xsl:variable name="targetelem" select="$target"/">

<xsl:if test="@xidtype='para">

<xsl:if test="not(ancestor::foreword)">

<xsl:choose>

<xsl:when test="$targetelem/ancestor::subpara1">

<fo:basic-link internal-destination="{@idref}"><xsl:attribute<br/>name="internal-destination"><xsl:value-of<br/>select="@xrefid"/></xsl:attribute>

<xsl:variable name="infoname"&lt;br"/>select="//idstatus/dmaddres/dmtitle/infoname"/>

<xsl:variable name="chapnum" select="book_chapter//@chap_num"/">

Section <xsl:value-of select="//@chap_num"/">.<xsl:number<br/>level="multiple" count="dmodule|para0" from="book_chapter"
format="1"/>.<xsl:number count="para0" from="dmodule" format="1"/"> -
'<xsl:value-of select="$xreftitle"/">'

</fo:basic-link>

</xsl:when>

<xsl:when test="$targetelem/ancestor::para0">

<fo:basic-link internal-destination="{@idref}"><xsl:attribute<br/>name="internal-destination"><xsl:value-of<br/>select="@xrefid"/></xsl:attribute>

<xsl:variable name="infoname"&lt;br"/>select="//idstatus/dmaddres/dmtitle/infoname"/>

<xsl:variable name="chapnum" select="book_chapter//@chap_num"/">

Section <xsl:value-of select="//@chap_num"/">.<xsl:number<br/>level="multiple" count="dmodule" from="book_chapter" format="1"/> -
'<xsl:value-of select="$xreftitle"/">'

</fo:basic-link>

</xsl:when>

</xsl:choose>

</xsl:if>

</fo:inline>

</xsl:if>

</xsl:if>

</xsl:template>

This is an example of how the XREF is setup in the XML at the moment.

<book_chapter chap_num="1" id="F423" linkid="48" omitfromcp="1">
<title>Organisation and Responsibilities</title>
<dmodule id="A5" dm_num="0" linkid="4769"&lt;br"/>docname="DMC-VBHL-GEN-01-01-0002-0000-000A-Z_000-00.xml">
<content>
<descript>
<para0 id="JG01">
<title>Test Title 1</title>
<para>Refer to <xref xrefid="6412-JG02a" xidtype="para" target="JG02"&lt;br"/>title="Test Title 2"/>.</para>
<subpara1 id="JG02">
<title>Test Title 2</title>
<para>Refer to <xref xrefid="6412-JG01a" xidtype="para" target="JG01"&lt;br"/>title="Test Title 1"/>.</para>
</subpara1>
</para0>
</descript>
</content>
</dmodule>
</book_chapter>

Kind Regards,
Juliette Gibb
Technical Publisher
Airline Publications
Safety Systems Division
Virgin Blue Airlines

Just from reading Clay's proposed XSL coding, I think you've got to change
this line:

> <xsl:variable name="targetelem" select="$target"/">
>
To:

<xsl:variable name="targetelem" select="id($target)"/">
>

--
Paul Nagai

Hi,

I've changed the variable targetelem to select the id($target) as Paul
suggested and have changed it back to call the parent::para0 rather than
ancestor.

However, now it is stopping when it tries to match the id to the target
node in the when expression for the para0 or subpara1 decision <xsl:when<br/>test="$targetelem/parent::para0">.

If I change the when statement to <xsl:when test="$targetelem"> then it
does output but I can't define if the parent of the target is within a
para0 or subpara1 which I need to do so that I can call out the correct
paragraph numbering of the target.

I have tried to create some when statements to call out the parents
within the $targetelem when statement but it doesn't work for me either.
I know the answer has got to be something simple but I just can't see
it. Any more suggestions would be a big help. Thank you. 🙂

<xsl:when test="$targetelem">

<xsl:choose>

<xsl:when test="parent::subpara1"><fo:inline<br/>color="green">TEST</fo:inline>

</xsl:when>

<xsl:when test="parent::para0"><fo:inline color="red">TEST</fo:inline>

</xsl:when>

</xsl:choose>


Cheers,
Juliette


OAG Best Low Cost Airline Of The Year

The content of this e-mail, including any attachments, is a confidential communication between Virgin Blue, Pacific Blue or a related entity (or the sender if this email is a private communication) and the intended addressee and is for the sole use of that intended addressee. If you are not the intended addressee, any use, interference with, disclosure or copying of this material is unauthorized and prohibited. If you have received this e-mail in error please contact the sender immediately and then delete the message and any attachment(s). There is no warranty that this email is error, virus or defect free. This email is also subject to copyright. No part of it should be reproduced, adapted or communicated without the written consent of the copyright owner. If this is a private communication it does not represent the views of Virgin Blue, Pacific Blue or their related entities. Please be aware that the contents of any emails sent to or from Virgin Blue, Pacific Blue or their related entities may be periodically monitored and reviewed. Virgin Blue, Pacific Blue and their related entities respect your privacy. Our privacy policy can be accessed from our website: www.virginblue.com.au

Hi Juliette--

In order for your inner tests to work as you intend, you need to change the context. To do that, you can use a for-each (even though there's only one target element, for-each will change the context to that element so that the Xpath expressions inside the for-each will be interpreted relative to the target element. So you want something like this:


<xsl:when test="$targetelem">

  <xsl:for-each select="$targetelem">

    <xsl:choose>

      <xsl:when test="parent::subpara1"><fo:inline color="green">TEST</fo:inline></xsl:when>

      <xsl:when test="parent::para0"><fo:inline color="red">TEST</fo:inline></xsl:when>

    </xsl:choose>

  </xsl:for-each>

</xsl:when>



But I think I see the problem now, after looking back at the markup sample you sent earlier. The problem is that the target element for your xref isn't a child or descendant of the subpara1 or the para0, it *is* the subpara1 or the para0. From your earlier markup sample:



<book_chapter chap_num="1" id="F423" linkid="48" omitfromcp="1">
<title>Organisation and Responsibilities</title>
<dmodule id="A5" dm_num="0" linkid="4769" docname="DMC-VBHL-GEN-01-01-0002-0000-000A-Z_000-00.xml">
<content>
<descript>
<para0 id="JG01">
<title>Test Title 1</title>
<para>Refer to <xref xrefid="6412-JG02a" xidtype="para" target="JG02" title="Test" title=" 2&quot;="/>.</para>
<subpara1 id="JG02">
<title>Test Title 2</title>
<para>Refer to <xref xrefid="6412-JG01a" xidtype="para" target="JG01" title="Test" title=" 1&quot;="/>.</para>
</subpara1>
</para0>
</descript>
</content>
</dmodule>
</book_chapter>



See how the id that matches the target in the xref is the actual para0 or subpara1 itself. So that makes the Xpath even simpler: just use $targetelem directly. To test which kind of thing it is, you can use the self axis, something like this:



<xsl:template match="xref">

  <xsl:variable name="targetelem" select="id(@target)"/">

  <xsl:choose>

    <xsl:when test="$targetelem/self::para0">

     

    </xsl:when>

    <xsl:when test="$targetelem/self::subpara1">

     

    </xsl:when>

  </xsl:choose>

</xsl:template>



Hopefully that will get you over the last hurdle.



--Clay



----------

Hi Clay,

Thank you for your help. I would love to say that worked but it is still
dropping out when it hits the <xsl:when test="$targetelem/self::para0">
everytime I put anything after the $targetelem it seems to loose the
plot. I've tried removing absolutely everything to the bare minimum and
even changed it all to be <xsl:if> or even a <xsl:value-of> and it just
doesn't like calling that particular variable.

Cheers,
Juliette

Hi Juliette--

Hmm. Maybe time for a little debugging. What do you get if you add some diagnostic messages to take a look at what it's actually grabbing for that variable? Something like this should be informative:

<xsl:template match="xref">
<xsl:variable name="targetelem" select="id(@target)"/">
<xsl:message>For link target <xsl:value-of select="@target"/">, I think the target element is a <xsl:value-of select="name($targetelem)"/">
</xsl:message>
<xsl:choose>
...etc.
</xsl:template>

If you're getting nulls or empty strings for the element name, it may be that your DTD isn't set up with the id attributes defined as formal ID attributes, which means the id() function won't work. In that case you might have to use an xsl:key hash to do the lookup. It would be something like this:


<xsl:key name="targetid" match="subpara1" |=" para0=" |=" {whatever=" other=" elements=" might=" be=" link=" targets}&quot;=" use="@id"/">

...
<xsl:template match="xref">
<xsl:variable name="targetelem" select="key('targetid',@target)"/">
<xsl:message>For link target <xsl:value-of select="@target"/">, I think the target element is a <xsl:value-of select="name($targetelem)"/">
</xsl:message>
<xsl:choose>
...etc.
</xsl:template>

--Clay

🙂 Clay you're a legend!! Thank you so much for your help, it is finally
working.

Just needed the magic key to solve the problem!

***Yay!! Does happy dance*** 🙂

Thank you. 🙂


Juliette,

It may now be obvious to others, but I don't see. In the interest of
completeness of this thread, would you post an example of the fix?

Thanks,
-Andy
\ / Andy Esslinger LM Aero Tech Order Data
_____-/\-_____ (817) 279-0442 Box 748, Mail Zone 4285
\_\/_/ (817) 777-3047 Fort Worth, TX 76101-0748

Whew! Glad we finally got there. 🙂

Hi Everyone,

Just to complete the thread like Andy suggested here is the final copy
of what was sorted out with much help everyone! 🙂

I'm still working on making sure it is pulling the correct targets
paragraph numbers but this is pretty much it.

Thank you all so much for all your help.

Cheers,
Juliette


<xsl:key name="targetid" match="subpara1" |=" para0&quot;=" use="@id"/">


<xsl:template match="xref">
<xsl:variable name="xidtype" select="translate(./@xidtype," $upper,<br="/>$lower)"/>
<xsl:variable name="target" select="./@target"/">
<xsl:variable name="xrefid" select="./@xrefid"/">
<xsl:variable name="targetelem" select="key('targetid',@target)"/">

<xsl:if test="@xidtype='para">
<xsl:variable name="dmid" select="@dmid"/">
<xsl:if test="not(@target='CommonSpecification')">
<fo:inline>
<xsl:if test="not(ancestor::foreword)">
<xsl:variable name="chapnum" select="book_chapter//@chap_num"/">
<xsl:variable name="infoname"&lt;br"/>select="//idstatus/dmaddres/dmtitle/infoname"/>
<fo:basic-link internal-destination="{@idref}"><xsl:attribute<br/>name="internal-destination"><xsl:value-of<br/>select="@xrefid"/></xsl:attribute>
Section <xsl:value-of select="//@chap_num"/">.<xsl:number level="single"&lt;br"/>count="dmodule" from="book_chapter"/>.</fo:basic-link>
<xsl:choose>

<xsl:when test="$targetelem/self::subpara1">
<fo:basic-link internal-destination="{@idref}"><xsl:attribute<br/>name="internal-destination"><xsl:value-of<br/>select="@xrefid"/></xsl:attribute>
<fo:inline>
<xsl:if test="$targetelem[position()&lt;=1]">
<xsl:number level="single" count="para0" from="dmodule"/">.<xsl:number<br/>value="count(following-sibling::node())" format="1"/></xsl:if>
<xsl:if test="$targetelem[position()">=2]">
<xsl:number level="single" count="para0" from="dmodule"/">.<xsl:number<br/>value="count(preceding-sibling::node())" format="1"/></xsl:if>
</fo:inline>
</fo:basic-link>
</xsl:when>
<xsl:when test="$targetelem/self::para0">
<fo:basic-link internal-destination="{@idref}"><xsl:attribute<br/>name="internal-destination"><xsl:value-of<br/>select="@xrefid"/></xsl:attribute>
<fo:inline>
<xsl:if test="$targetelem[position()&lt;=1]">
<xsl:number value="count(following-sibling::node())" format="1"&lt;br"/>from="ancestor::dmodule"/></xsl:if>
<xsl:if test="$targetelem[position()">=2]">
<xsl:number value="count(preceding-sibling::node())" format="1"&lt;br"/>from="ancestor::dmodule"/></xsl:if>
</fo:inline>
</fo:basic-link>
</xsl:when>
<xsl:otherwise>
<fo:inline>Reference Not Found</fo:inline>
</xsl:otherwise>
</xsl:choose>
- '<xsl:value-of select="@title"/">'
</xsl:if>
</fo:inline>
</xsl:if>
</xsl:if>
</xsl:template>
Announcements