Subject: Re: [xsl] Grouping repeating elements within repeating elements From: Cynthia.Arangua@xxxxxxxxxxxxxx Date: Wed, 5 Dec 2007 12:42:46 -0600 |
Strike what I had asked for before. I think I got that working. But now, I am running into another issue. This code is basically building out an FAQ page. But my problem really is is that there are cases where there will be no headings (i.e. a parent node). If that is the case, I just need to display the questions and answers and bypass wrapping in a div tag that the values from the headings would produce. I have it working now where if there are no headings, then just display the questions and answers. But unfourtunately, the xsl:if that I have in place is getting stepped into even by questions and answers that do have headings and they are showing up as duplicates. The XML input below is still the same but the only variance is that I pull in the content_category_faq value and pass that value into a query to pull back all the XML objects that have value and thus display the questions and answers. The code is attached below and I have it commented where a more effective if logic is needed. I just can't seem to figure out how to get around the duplicate entries in the questions and answers where there are indeed headings. Thank you so much for any suggestions. ----------------------------------------------------------------- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:functx="http://www.functx.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:java="http://xml.apache.org/xslt/java" xmlns:xalan="http://xml.apache.org/xalan" version="1.0" exclude-result-prefixes="java xalan"> <xsl:output method="html"/> <!--######################################################################################--> <!--Parameters for XDQL processing--> <!--######################################################################################--> <xsl:param name="DMS_SESSION_ID" select="'default value'"/> <xsl:param name="DMS_INPUT_OBJECT_ID"/> <!--######################################################################################--> <!--Need to query the get the content_category values in the FAQ Listing Object to build the Listings--> <!--######################################################################################--> <xsl:param name="faq" select="content/faq_listing"/> <xsl:param name="listing_content_category" select="content/faq_listing/category/content_category_faq"/> <xsl:param name="heading" select="content/faq_listing/heading"/> <!--######################################################################################--> <!--MAIN TEMPLATE CALL--> <!--######################################################################################--> <xsl:template match="/"> <html> <head> <style type="text/css"> .linkMore { font: bold 10px Tahoma; background: url("bulletMore.gif") no-repeat left; vertical-align: baseline; padding: 0 7px 0 0; margin: 0; } .content_hiearchy_display { display:block; } .content_hiearchy_hidden { display:none; ) </style> <script type="text/javascript"> function ContentHiearchy_FAQ (div_name){ alert(div_name); var divToShow=document.getElementById(div_name); if (divToShow.style.display=='block'){ divToShow.style.display='none'; } else{ divToShow.style.display='block'; } } </script> </head> <body> <xsl:call-template name="next-heading"> <xsl:with-param name="faqs" select="/content/faq_listing"/> </xsl:call-template> </body> </html> <!--start everything off with the first heading using all FAQs available--> </xsl:template> <!--process the next level of heading distinction--> <xsl:template name="next-heading"> <xsl:param name="index" select="1"/> <xsl:param name="indent" select="''"/> <xsl:param name="faqs" select="/.."/> <!--determine if there are any headings at this level--> <xsl:if test="$faqs[heading[$index]]"> <!--then there are levels of heading still to separate--> <xsl:for-each select="$faqs"> <xsl:variable name="generatingOuterId" select="generate-id(.)"/> <xsl:if test="generate-id(.)= generate-id($faqs[heading[$index]= current()/heading[$index]])"> <!--this is a common heading, so display it--> <xsl:variable name="generatingHeaderId" select="concat(heading[$index],$generatingOuterId)"/> <xsl:if test="string(heading[$index])"> <xsl:text disable-output-escaping="yes"><![CDATA[<a class='linkMore' href='#' onclick="ContentHiearchy_FAQ(']]></xsl:text> <xsl:value-of select="$generatingHeaderId"/> <xsl:text disable-output-escaping="yes"><![CDATA[')">]]></xsl:text> <xsl:value-of select="concat($indent,heading[$index])"/> <xsl:text disable-output-escaping="yes"><![CDATA[</a><br/> <DIV id="]]></xsl:text> <xsl:value-of select="$generatingHeaderId"/> <xsl:text disable-output-escaping="yes"><![CDATA[" class="content_hiearchy_hidden">]]></xsl:text> <!--determine if there is any information at the next level of depth--> <xsl:call-template name="next-heading"> <xsl:with-param name="index" select="$index + 1"/> <xsl:with-param name="indent" select="concat($indent,'   ')"/> <xsl:with-param name="faqs" select="$faqs[heading[$index]= current()/heading[$index]]"/> </xsl:call-template> <xsl:text disable-output-escaping="yes"><![CDATA[</div>]]></xsl:text> </xsl:if> </xsl:if> <!--*********************************************--> <!--THERE IS NO HEADER--> <!--*********************************************--> <!--NEED A MORE EFFECTIVE MECHANISM TO CHECK FOR CATEGORIES WITH NO HEADINGS--> <!--THIS IF STATEMENT IS SUFFICIENT FOR PULLING IN QUESTIONS AND ANSWERS WITH NO HEADING BUT PUTS IN COPIES OF QUESTIONS AND ANSWERS IF THERE IS A HEADING--> <xsl:if test="not(string(heading[$index]))"> <xsl:value-of select="$index"></xsl:value-of> WE ARE IN THE NO HEADER CODE <xsl:for-each select="category/content_category_faq"> <xsl:variable name="generatingCategoryIdOuter" select="generate-id(.)"/> <xsl:variable name="content_cat" select="."/> <xsl:variable name="gettingObjAttrs">select r_object_id from sargento_portal_document where any content_category= '<xsl:value-of select="$content_cat"/>' and r_object_id!='<xsl:value-of select="$DMS_INPUT_OBJECT_ID"/>' and content_type='FAQ' and r_object_id not in (select parent_id from dm_relation where child_id in (select r_object_id from sargento_portal_document where object_name='FAQ_Listing_Template.xml')) </xsl:variable> <xsl:variable name="gettingObjAttrs_results"> <xsl:call-template name="XDQL"> <xsl:with-param name="dql" select="string($gettingObjAttrs)"/> <xsl:with-param name="includecontent" select="string('true')"/> </xsl:call-template> </xsl:variable> <xsl:if test="string(xalan:nodeset($gettingObjAttrs_results)/xdql/object/r_object_id)"> <xsl:for-each select="xalan:nodeset($gettingObjAttrs_results)/xdql/object/r_object_id"> <xsl:variable name="idOfXML" select="."/> <xsl:variable name="generatingCategoryId" select="generate-id(.)"/> <xsl:variable name="idOfPair" select="concat($generatingCategoryIdOuter,(concat($generatingCategoryId,$idOfXML)))"/> <xsl:text disable-output-escaping="yes"><![CDATA[<a class='linkMore' href='#' onclick="ContentHiearchy_FAQ(']]></xsl:text> <xsl:value-of select="$idOfPair"/> <xsl:text disable-output-escaping="yes"><![CDATA[')">]]></xsl:text> <xsl:value-of select="concat($indent,../content/content/faq/question)"/> <xsl:text disable-output-escaping="yes"><![CDATA[</a>]]></xsl:text> <br/> <xsl:text disable-output-escaping="yes"><![CDATA[<div class="content_hiearchy_hidden linkMore " id="]]></xsl:text> <xsl:value-of select="$idOfPair"/> <xsl:text disable-output-escaping="yes"><![CDATA[">]]></xsl:text> <xsl:value-of select="concat($indent,../content/content/faq/answer)"/> <xsl:if test="not(string(../content/content/faq_document))"> <xsl:text disable-output-escaping="yes"><![CDATA[</div>]]></xsl:text> </xsl:if> <xsl:if test="string(../content/content/faq_document)"> <xsl:for-each select="../content/content/faq_document"> <xsl:variable name="getSelectedObject" select="document/processing-instruction('dctmEditor')"/> <xsl:variable name="objectId" select="substring-after($getSelectedObject,'selectedObject=')"/> <xsl:variable name="obj" select="substring($objectId,1,16)"/> <xsl:variable name="gettingFAQDocAttrs">select r_object_id, title from sargento_portal_document where r_object_id='<xsl:value-of select="$obj"/>'</xsl:variable> <xsl:variable name="gettingFAQDocAttrs_results"> <xsl:call-template name="XDQL"> <xsl:with-param name="dql" select="string($gettingFAQDocAttrs)"/> <xsl:with-param name="includecontent" select="string('false')"/> </xsl:call-template> </xsl:variable> <xsl:variable name="document_title" select="xalan:nodeset($gettingFAQDocAttrs_results)/xdql/object/title"/> <xsl:if test="string(document)"> <br/> <xsl:value-of select="$indent"/> <a> <xsl:attribute name="href"><xsl:value-of select="document"/></xsl:attribute> <xsl:attribute name="target">_blank</xsl:attribute> <xsl:value-of select="$document_title"/> <br/> </a> </xsl:if> </xsl:for-each> </xsl:if> <xsl:text disable-output-escaping="yes"><![CDATA[</div>]]></xsl:text> </xsl:for-each> </xsl:if> </xsl:for-each> </xsl:if> <!--*********************************************--> <!--END OF CHECKING FOR NO HEADER--> <!--*********************************************--> </xsl:for-each> </xsl:if> <xsl:for-each select="$faqs[heading[$index - 1] and not( heading[$index] )]/ category/content_category_faq"> <xsl:variable name="generatingCategoryIdOuter" select="generate-id(.)"/> <xsl:variable name="content_cat" select="."/> <xsl:variable name="gettingObjAttrs">select r_object_id from sargento_portal_document where any content_category= '<xsl:value-of select="$content_cat"/>' and r_object_id!='<xsl:value-of select="$DMS_INPUT_OBJECT_ID"/>' and content_type='FAQ' and r_object_id not in (select parent_id from dm_relation where child_id in (select r_object_id from sargento_portal_document where object_name='FAQ_Listing_Template.xml')) </xsl:variable> <xsl:variable name="gettingObjAttrs_results"> <xsl:call-template name="XDQL"> <xsl:with-param name="dql" select="string($gettingObjAttrs)"/> <xsl:with-param name="includecontent" select="string('true')"/> </xsl:call-template> </xsl:variable> <xsl:if test="string(xalan:nodeset($gettingObjAttrs_results)/xdql/object/r_object_id)"> <xsl:for-each select="xalan:nodeset($gettingObjAttrs_results)/xdql/object/r_object_id"> <xsl:variable name="idOfXML" select="."/> <xsl:variable name="generatingCategoryId" select="generate-id(.)"/> <xsl:variable name="idOfPair" select="concat($generatingCategoryIdOuter,(concat($generatingCategoryId,$idOfXML)))"/> <xsl:text disable-output-escaping="yes"><![CDATA[<a class='linkMore' href='#' onclick="ContentHiearchy_FAQ(']]></xsl:text> <xsl:value-of select="$idOfPair"/> <xsl:text disable-output-escaping="yes"><![CDATA[')">]]></xsl:text> <xsl:value-of select="concat($indent,../content/content/faq/question)"/> <xsl:text disable-output-escaping="yes"><![CDATA[</a>]]></xsl:text> <br/> <xsl:text disable-output-escaping="yes"><![CDATA[<div class="content_hiearchy_hidden linkMore " id="]]></xsl:text> <xsl:value-of select="$idOfPair"/> <xsl:text disable-output-escaping="yes"><![CDATA[">]]></xsl:text> <xsl:value-of select="concat($indent,../content/content/faq/answer)"/> <xsl:if test="not(string(../content/content/faq_document))"> <xsl:text disable-output-escaping="yes"><![CDATA[</div>]]></xsl:text> </xsl:if> <xsl:if test="string(../content/content/faq_document)"> <xsl:for-each select="../content/content/faq_document"> <xsl:variable name="getSelectedObject" select="document/processing-instruction('dctmEditor')"/> <xsl:variable name="objectId" select="substring-after($getSelectedObject,'selectedObject=')"/> <xsl:variable name="obj" select="substring($objectId,1,16)"/> <xsl:variable name="gettingFAQDocAttrs">select r_object_id, title from sargento_portal_document where r_object_id='<xsl:value-of select="$obj"/>'</xsl:variable> <xsl:variable name="gettingFAQDocAttrs_results"> <xsl:call-template name="XDQL"> <xsl:with-param name="dql" select="string($gettingFAQDocAttrs)"/> <xsl:with-param name="includecontent" select="string('false')"/> </xsl:call-template> </xsl:variable> <xsl:variable name="document_title" select="xalan:nodeset($gettingFAQDocAttrs_results)/xdql/object/title"/> <xsl:if test="string(document)"> <br/> <xsl:value-of select="$indent"/> <a> <xsl:attribute name="href"><xsl:value-of select="document"/></xsl:attribute> <xsl:attribute name="target">_blank</xsl:attribute> <xsl:value-of select="$document_title"/> <br/> </a> </xsl:if> </xsl:for-each> </xsl:if> <xsl:text disable-output-escaping="yes"><![CDATA[</div>]]></xsl:text> </xsl:for-each> </xsl:if> </xsl:for-each> </xsl:template> <xsl:template name="XDQL"> <xsl:param name="dql"/> <xsl:param name="includecontent" select="string('false')"/> <xsl:variable name="pdql" select="string($dql)"/> <xsl:variable name="xdql" select="java:com.documentum.xml.xdql.DfXmlQuery.new()"/> <xsl:variable name="init" select="java:init($xdql)"/> <xsl:variable name="setDql" select="java:setDql($xdql,$pdql)"/> <xsl:variable name="setContentEncoding" select="java:setContentEncoding($xdql,'dom')"/> <xsl:variable name="setContentFormat" select="java:setContentFormat($xdql,'xml')"/> <xsl:variable name="setRootNode" select="java:setRootNode($xdql,'xdql')"/> <xsl:variable name="Repeatingasnested" select="java:setRepeatingAsNested($xdql,false())"/> <xsl:choose> <xsl:when test="$includecontent='false'"> <xsl:variable name="param_includeContent" select="java:includeContent($xdql,false())"/> </xsl:when> <xsl:otherwise> <xsl:variable name="param_includeContent" select="java:includeContent($xdql,true())"/> </xsl:otherwise> </xsl:choose> <xsl:variable name="execute" select="java:execute($xdql,'DF_READ_QUERY',$DMS_SESSION_ID)"/> <xsl:variable name="results" select="java:getXMLDOM($xdql)"/> <xsl:copy-of select="$results"/> </xsl:template> </xsl:stylesheet> -----Cynthia.Arangua@xxxxxxxxxxxxxx wrote: ----- To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx From: Cynthia.Arangua@xxxxxxxxxxxxxx Date: 12/04/2007 11:03AM Subject: Re: [xsl] Grouping repeating elements within repeating elements This solution worked wonderfully but I have two more questions. How would you generate a unique id for each layer in the output? I tried to do generate-id(.) but in some cases, it generated the same id so I have tried to add in documentum specific ids that it pulls from the database but not sure I feel completely comfortable with that approach. Also, how would we produce the /category/content_category_faq if there we NO headings. I am trying to come up with a solution for that one right now as well. Thanks! -----"G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx> wrote: ----- To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx> From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx> Date: 11/26/2007 08:31PM Subject: Re: [xsl] Grouping repeating elements within repeating elements At 2007-11-26 13:08 -0700, Cynthia Arangua wrote: >I have been doing XSLT for about four years now and this input XML >has me a little stumped as to how to implement. I believe I am >using Xalan 2.6 (bundled as part of an EMC Documentum product called >WebPublisher) and the only version it supports currently is XSLT 1.0. This is a particularly difficult problem for XSLT 1.0 because of the organization of the grouping. >Here is the XML input: >... >Basically, I need to group any category/content_category_faq under >the appropriate heading designation so like the following: > >Benefits > Health > Medical Coverage > Medical Coverage-PPO > Medical Coverage-HMO > Dental > Financial > Flexible Spending >Life Events > Getting Married > Adoption > >I am in the introductory stages on development on this so I don't >have any existing XSL to demonstrate but I am hoping to make some >headway today so I can repost but any initial help would be very >cool. I am working on some recurse logic as we speak. I, too, had to use recursive logic to address this. A complete solution is below. As I've often posted, I'm using variables for grouping because of the sub-document context (keys have document-wide context in XSLT 1.0 but can be accessed in a limited fashion in XSLT 2.0). What was interesting is the organization of your headers ... I made the assumptions that the order is critically important: it isn't just that the headers are the same, but that the same headers are in the same relative position to each other as children of FAQs. I hope the code below helps ... the output matches your requirement. . . . . . . . . . . Ken T:\ftemp>type cindy.xml <?xml version="1.0" encoding="UTF-8"?> <content> <faq_listing> <heading>Benefits</heading> <heading>Health</heading> <heading>Medical Coverage</heading> <category> <content_category_faq>Medical Coverage - PPO</content_category_faq> </category> <category> <content_category_faq>Medical Coverage - HMO</content_category_faq> </category> </faq_listing> <faq_listing> <heading>Benefits</heading> <heading>Health</heading> <category> <content_category_faq>Dental</content_category_faq> </category> </faq_listing> <faq_listing> <heading>Benefits</heading> <heading>Financial</heading> <category> <content_category_faq>Flexible Spending</content_category_faq> </category> </faq_listing> <faq_listing> <heading>Life Events</heading> <category> <content_category_faq>Getting Married</content_category_faq> </category> <category> <content_category_faq>Adoption</content_category_faq> </category> </faq_listing> </content> T:\ftemp>type cindy.xsl <?xml version="1.0" encoding="US-ASCII"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="text"/> <xsl:template match="/"> <!--start everything off with the first heading using all FAQs available--> <xsl:call-template name="next-heading"> <xsl:with-param name="faqs" select="/content/faq_listing"/> </xsl:call-template> </xsl:template> <!--process the next level of heading distinction--> <xsl:template name="next-heading"> <xsl:param name="index" select="1"/> <xsl:param name="indent" select="''"/> <xsl:param name="faqs" select="/.."/> <!--determine if there are any headings at this level--> <xsl:if test="$faqs[heading[$index]]"> <!--then there are levels of heading still to separate--> <xsl:for-each select="$faqs"> <xsl:if test="generate-id(.)= generate-id($faqs[heading[$index]= current()/heading[$index]])"> <!--this is a common heading, so display it--> <xsl:value-of select="concat($indent,heading[$index])"/><xsl:text> </xsl:text> <!--determine if there is any information at the next level of depth--> <xsl:call-template name="next-heading"> <xsl:with-param name="index" select="$index + 1"/> <xsl:with-param name="indent" select="concat($indent,' ')"/> <xsl:with-param name="faqs" select="$faqs[heading[$index]= current()/heading[$index]]"/> </xsl:call-template> </xsl:if> </xsl:for-each> </xsl:if> <!--determine if there are any non-headings at this level--> <xsl:for-each select="$faqs[heading[$index - 1] and not( heading[$index] )]/ category/content_category_faq"> <!--and display them--> <xsl:value-of select="concat($indent,.)"/><xsl:text> </xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet> T:\ftemp>call xslt cindy.xml cindy.xsl cindy.txt T:\ftemp>echo on T:\ftemp>type cindy.txt Benefits Health Medical Coverage Medical Coverage - PPO Medical Coverage - HMO Dental Financial Flexible Spending Life Events Getting Married Adoption T:\ftemp>rem Done! -- Comprehensive in-depth XSLT2/XSL-FO1.1 classes: Austin TX,Jan-2008 World-wide corporate, govt. & user group XML, XSL and UBL training RSS feeds: publicly-available developer resources and training G. Ken Holman mailto:gkholman@xxxxxxxxxxxxxxxxxxxx Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/ Box 266, Kars, Ontario CANADA K0A-2E0 +1(613)489-0999 (F:-0995) Male Cancer Awareness Nov'07 http://www.CraneSoftwrights.com/s/bc Legal business disclaimers: http://www.CraneSoftwrights.com/legal
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Grouping repeating elemen, Cynthia . Arangua | Thread | Re: [xsl] Grouping repeating elemen, G. Ken Holman |
Re: [xsl] Problem with xsl:template, Andrew Welch | Date | Re: [xsl] Help using recursion on d, David Carlisle |
Month |