Jump to content
Sign in to follow this  
Yvonne Garcia

Hyperlinking portal field

Recommended Posts

I've searched through the archive and can't quite find an answer to this issue. Any help would be appreciated.

Here's the background info:

FMPro 7 Advanced shared via CWP.

One file, multiple tables.

One table is Projects; another table is Personnel. I can get the Personnel related to Project to display, no problem using the following code:

<xsl:when test="count(fmrs:relatedset[@table='Personnel']/fmrs:record)>0">

Share this post


Link to post
Share on other sites

The problem is that the context is changed when you change the XPath in the xsl:for-each statement.

"Context" means the actual view or position of your XSLT transformation in your XML resultset tree. You can set e.g. the context with <xsl:template select="..."> or with <xsl:for-each select="...">

In your double-nested loop, you set the context to /fmrs:fmresultset/fmrs:resultset/fmrs:relatedset[@table='Personnel']/fmrs:record/fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data within the inner loop. Therefore, within the inner loop, the XLST transform engine would see all the nodes and their subnodes conforming to this XPath. Now you try to access fmrs:field[@name='Personnel::id_prsn']/fmrs:data relative to this XPath in your <xsl:with-param statement, e.g. the absolute XPath would be /fmrs:fmresultset/fmrs:resultset/fmrs:relatedset[@table='Personnel']/fmrs:record/fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data/fmrs:field[@name='Personnel::id_prsn']/fmrs:data . Of course this can not work.

One solution would be to change the relative path to something like ../../fmrs:field[@name='Personnel::id_prsn']/fmrs:data . Depending on the number of cycles the loop has to do this can be bad for performance, because the XPath has to be evaluated in every cycle. Better is to save your person id in a variable before entering the loop, and use the variable then:

<xsl:when test="count(fmrs:relatedset[@table='Personnel']/fmrs:record)>0">

<xsl:for-each select="fmrs:relatedset[@table='Personnel']/fmrs:record">

<!-- variable definition here -->

<xsl:variable name="person_id" select="fmrs:field[@name='Personnel::id_prsn']/fmrs:data[1]"/>

<xsl:for-each select="fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data">

<xsl:if test="position() != 1"><br/></xsl:if>

<a>

<xsl:attribute name="href">

<xsl:call-template name="link-prsnrecord">

<!-- use the variable here -->

<xsl:with-param name="id_prsn" select="$person_id"/>

</xsl:call-template>

</xsl:attribute>

<xsl:value-of select="."/>

</a>

<br/>

Ok? smirk.gif

Martin

Share this post


Link to post
Share on other sites

The problem is that the context is changed when you change the XPath in the xsl:for-each statement.

"Context" means the actual view or position of your XSLT transformation in your XML resultset tree. You can set e.g. the context with <xsl:template select="..."> or with <xsl:for-each select="...">

In your double-nested loop, you set the context to /fmrs:fmresultset/fmrs:resultset/fmrs:relatedset[@table='Personnel']/fmrs:record/fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data within the inner loop. Therefore, within the inner loop, the XLST transform engine would see all the nodes and their subnodes conforming to this XPath. Now you try to access fmrs:field[@name='Personnel::id_prsn']/fmrs:data relative to this XPath in your <xsl:with-param statement, e.g. the absolute XPath would be /fmrs:fmresultset/fmrs:resultset/fmrs:relatedset[@table='Personnel']/fmrs:record/fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data/fmrs:field[@name='Personnel::id_prsn']/fmrs:data . Of course this can not work.

One solution would be to change the relative path to something like ../../fmrs:field[@name='Personnel::id_prsn']/fmrs:data . Depending on the number of cycles the loop has to do this can be bad for performance, because the XPath has to be evaluated in every cycle. Better is to save your person id in a variable before entering the loop, and use the variable then:

<xsl:when test="count(fmrs:relatedset[@table='Personnel']/fmrs:record)>0">

<xsl:for-each select="fmrs:relatedset[@table='Personnel']/fmrs:record">

<!-- variable definition here -->

<xsl:variable name="person_id" select="fmrs:field[@name='Personnel::id_prsn']/fmrs:data[1]"/>

<xsl:for-each select="fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data">

<xsl:if test="position() != 1"><br/></xsl:if>

<a>

<xsl:attribute name="href">

<xsl:call-template name="link-prsnrecord">

<!-- use the variable here -->

<xsl:with-param name="id_prsn" select="$person_id"/>

</xsl:call-template>

</xsl:attribute>

<xsl:value-of select="."/>

</a>

<br/>

Ok? smirk.gif

Martin

Share this post


Link to post
Share on other sites

The problem is that the context is changed when you change the XPath in the xsl:for-each statement.

"Context" means the actual view or position of your XSLT transformation in your XML resultset tree. You can set e.g. the context with <xsl:template select="..."> or with <xsl:for-each select="...">

In your double-nested loop, you set the context to /fmrs:fmresultset/fmrs:resultset/fmrs:relatedset[@table='Personnel']/fmrs:record/fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data within the inner loop. Therefore, within the inner loop, the XLST transform engine would see all the nodes and their subnodes conforming to this XPath. Now you try to access fmrs:field[@name='Personnel::id_prsn']/fmrs:data relative to this XPath in your <xsl:with-param statement, e.g. the absolute XPath would be /fmrs:fmresultset/fmrs:resultset/fmrs:relatedset[@table='Personnel']/fmrs:record/fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data/fmrs:field[@name='Personnel::id_prsn']/fmrs:data . Of course this can not work.

One solution would be to change the relative path to something like ../../fmrs:field[@name='Personnel::id_prsn']/fmrs:data . Depending on the number of cycles the loop has to do this can be bad for performance, because the XPath has to be evaluated in every cycle. Better is to save your person id in a variable before entering the loop, and use the variable then:

<xsl:when test="count(fmrs:relatedset[@table='Personnel']/fmrs:record)>0">

<xsl:for-each select="fmrs:relatedset[@table='Personnel']/fmrs:record">

<!-- variable definition here -->

<xsl:variable name="person_id" select="fmrs:field[@name='Personnel::id_prsn']/fmrs:data[1]"/>

<xsl:for-each select="fmrs:field[@name='Personnel::x_prsn_LastName_FirstName']/fmrs:data">

<xsl:if test="position() != 1"><br/></xsl:if>

<a>

<xsl:attribute name="href">

<xsl:call-template name="link-prsnrecord">

<!-- use the variable here -->

<xsl:with-param name="id_prsn" select="$person_id"/>

</xsl:call-template>

</xsl:attribute>

<xsl:value-of select="."/>

</a>

<br/>

Ok? smirk.gif

Martin

Share this post


Link to post
Share on other sites

Martin,

Thank you for the great explanation and the code. That worked well with the Personnel situation I outlined. After reading your post, I thought I understood the issue with "Context" so I tried my hand at another similar situation. However, I wound up with the same problem I had with the Personnel situation. It looks like a link but the variable isn't being passed. Can you point out where my thinking/coding is flawed?

Here's the code I created based on the personnel example you shared with me:

<td align="left" valign="top"><br/>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<!-- variable definition here -->

<xsl:variable name="whynot" select="fmrs:field[@name='Project_Open::id_master']/fmrs:data[1]"/>

<xsl:for-each select="fmrs:field[@name='Project_Open::prj_title']/fmrs:data">

<xsl:if test="position() != 1"><br/></xsl:if>

<a>

<xsl:attribute name="href">

<xsl:call-template name="link-prjrecord-pi">

<!-- use the variable here -->

<xsl:with-param name="id_master" select="$whynot"/>

</xsl:call-template>

</xsl:attribute>

<xsl:value-of select="."/>

</a>

</xsl:for-each>

</xsl:for-each>

</td>

It DOES work if I go back to my clunky workaround of linking on some static text instead of the dynamic field:

<tr>

<td>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<xsl:for-each select="fmrs:field[@name='Project_Open::prj_title']/fmrs:data">

<xsl:if test="position() != 1"><br/>

</xsl:if> <xsl:value-of select="fmxslt:break_encode(.)" disable-output-escaping="yes" /><br/>

<xsl:if test=". = ''"> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>

</xsl:if> </xsl:for-each>

</xsl:for-each>

<br/> </td>

<td align="left"> <br/>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<xsl:for-each select="fmrs:field[@name='Project_Open::id_master']/fmrs:data">

<xsl:if test="position() != 1"><br/>

</xsl:if> <a> <xsl:attribute name="href"> <xsl:call-template name="link-prjrecord-pi">

<xsl:with-param name="id_master" select="."/> </xsl:call-template> </xsl:attribute>

(view) </a><br/>

<xsl:if test=". = ''"> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>

</xsl:if> </xsl:for-each>

</xsl:for-each> <br/> </td>

</tr>

Thanks in advance for the help and the education.

- Yvonne

Share this post


Link to post
Share on other sites

Martin,

Thank you for the great explanation and the code. That worked well with the Personnel situation I outlined. After reading your post, I thought I understood the issue with "Context" so I tried my hand at another similar situation. However, I wound up with the same problem I had with the Personnel situation. It looks like a link but the variable isn't being passed. Can you point out where my thinking/coding is flawed?

Here's the code I created based on the personnel example you shared with me:

<td align="left" valign="top"><br/>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<!-- variable definition here -->

<xsl:variable name="whynot" select="fmrs:field[@name='Project_Open::id_master']/fmrs:data[1]"/>

<xsl:for-each select="fmrs:field[@name='Project_Open::prj_title']/fmrs:data">

<xsl:if test="position() != 1"><br/></xsl:if>

<a>

<xsl:attribute name="href">

<xsl:call-template name="link-prjrecord-pi">

<!-- use the variable here -->

<xsl:with-param name="id_master" select="$whynot"/>

</xsl:call-template>

</xsl:attribute>

<xsl:value-of select="."/>

</a>

</xsl:for-each>

</xsl:for-each>

</td>

It DOES work if I go back to my clunky workaround of linking on some static text instead of the dynamic field:

<tr>

<td>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<xsl:for-each select="fmrs:field[@name='Project_Open::prj_title']/fmrs:data">

<xsl:if test="position() != 1"><br/>

</xsl:if> <xsl:value-of select="fmxslt:break_encode(.)" disable-output-escaping="yes" /><br/>

<xsl:if test=". = ''"> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>

</xsl:if> </xsl:for-each>

</xsl:for-each>

<br/> </td>

<td align="left"> <br/>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<xsl:for-each select="fmrs:field[@name='Project_Open::id_master']/fmrs:data">

<xsl:if test="position() != 1"><br/>

</xsl:if> <a> <xsl:attribute name="href"> <xsl:call-template name="link-prjrecord-pi">

<xsl:with-param name="id_master" select="."/> </xsl:call-template> </xsl:attribute>

(view) </a><br/>

<xsl:if test=". = ''"> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>

</xsl:if> </xsl:for-each>

</xsl:for-each> <br/> </td>

</tr>

Thanks in advance for the help and the education.

- Yvonne

Share this post


Link to post
Share on other sites

Martin,

Thank you for the great explanation and the code. That worked well with the Personnel situation I outlined. After reading your post, I thought I understood the issue with "Context" so I tried my hand at another similar situation. However, I wound up with the same problem I had with the Personnel situation. It looks like a link but the variable isn't being passed. Can you point out where my thinking/coding is flawed?

Here's the code I created based on the personnel example you shared with me:

<td align="left" valign="top"><br/>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<!-- variable definition here -->

<xsl:variable name="whynot" select="fmrs:field[@name='Project_Open::id_master']/fmrs:data[1]"/>

<xsl:for-each select="fmrs:field[@name='Project_Open::prj_title']/fmrs:data">

<xsl:if test="position() != 1"><br/></xsl:if>

<a>

<xsl:attribute name="href">

<xsl:call-template name="link-prjrecord-pi">

<!-- use the variable here -->

<xsl:with-param name="id_master" select="$whynot"/>

</xsl:call-template>

</xsl:attribute>

<xsl:value-of select="."/>

</a>

</xsl:for-each>

</xsl:for-each>

</td>

It DOES work if I go back to my clunky workaround of linking on some static text instead of the dynamic field:

<tr>

<td>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<xsl:for-each select="fmrs:field[@name='Project_Open::prj_title']/fmrs:data">

<xsl:if test="position() != 1"><br/>

</xsl:if> <xsl:value-of select="fmxslt:break_encode(.)" disable-output-escaping="yes" /><br/>

<xsl:if test=". = ''"> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>

</xsl:if> </xsl:for-each>

</xsl:for-each>

<br/> </td>

<td align="left"> <br/>

<xsl:for-each select="fmrs:relatedset[@table='Project_Open']/fmrs:record">

<xsl:for-each select="fmrs:field[@name='Project_Open::id_master']/fmrs:data">

<xsl:if test="position() != 1"><br/>

</xsl:if> <a> <xsl:attribute name="href"> <xsl:call-template name="link-prjrecord-pi">

<xsl:with-param name="id_master" select="."/> </xsl:call-template> </xsl:attribute>

(view) </a><br/>

<xsl:if test=". = ''"> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>

</xsl:if> </xsl:for-each>

</xsl:for-each> <br/> </td>

</tr>

Thanks in advance for the help and the education.

- Yvonne

Share this post


Link to post
Share on other sites

Hmm, the upper code looks ok IMHO. Might it be that the id_master field is missing in Project_Open portal on the layout you use?

Add a line <textarea rows="10" cols="80"><xsl:copy-of select="$whynot"/></textarea> after your variable definition in order to debug the variable (to show its contents).

I also noticed that the XML resultset tree depends on the order in which one has placed the fields on the layout. E.g. if you place first fields of the main table, than of the related table, than again of the main table, than again of the related table, your fmrs:relatedset part is split into two parts, and the XSLT might have problems to address the parts correctly. The best is then to rebuild the layout.

Martin

Share this post


Link to post
Share on other sites

Hmm, the upper code looks ok IMHO. Might it be that the id_master field is missing in Project_Open portal on the layout you use?

Add a line <textarea rows="10" cols="80"><xsl:copy-of select="$whynot"/></textarea> after your variable definition in order to debug the variable (to show its contents).

I also noticed that the XML resultset tree depends on the order in which one has placed the fields on the layout. E.g. if you place first fields of the main table, than of the related table, than again of the main table, than again of the related table, your fmrs:relatedset part is split into two parts, and the XSLT might have problems to address the parts correctly. The best is then to rebuild the layout.

Martin

Share this post


Link to post
Share on other sites

Hmm, the upper code looks ok IMHO. Might it be that the id_master field is missing in Project_Open portal on the layout you use?

Add a line <textarea rows="10" cols="80"><xsl:copy-of select="$whynot"/></textarea> after your variable definition in order to debug the variable (to show its contents).

I also noticed that the XML resultset tree depends on the order in which one has placed the fields on the layout. E.g. if you place first fields of the main table, than of the related table, than again of the main table, than again of the related table, your fmrs:relatedset part is split into two parts, and the XSLT might have problems to address the parts correctly. The best is then to rebuild the layout.

Martin

Share this post


Link to post
Share on other sites

My first thought was that the id_master field was missing from the portal as well. But, alas, it wasn't.

I rebuilt the layout and that did the trick!

Thank you very much, Martin.

Share this post


Link to post
Share on other sites

My first thought was that the id_master field was missing from the portal as well. But, alas, it wasn't.

I rebuilt the layout and that did the trick!

Thank you very much, Martin.

Share this post


Link to post
Share on other sites

My first thought was that the id_master field was missing from the portal as well. But, alas, it wasn't.

I rebuilt the layout and that did the trick!

Thank you very much, Martin.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Who Viewed the Topic

    1 member has viewed this topic:
    john9210 
×

Important Information

By using this site, you agree to our Terms of Use.