[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Restrict Key to specific parent

Subject: Restrict Key to specific parent
From: "Ty Molchany" <ty.molchany@xxxxxxxxx>
Date: Wed, 29 Nov 2006 14:44:58 -0500
ty molchany
Hello,
This is as simple of an example, hitting the main scenarios, I could
come up with.

I will try and be as clear and unambiguous as possible. I did research
throughout the xsl-list archive and found posts that were close, but
did not really hit my issue here.
I will start with an input xml, show the output expected and then show
you what I tried and it's short comings. So here goes.

Input XML:
<Root>
<Info>
<Prod name="Red"/>
<Prod name="Blue"/>
<Prod name="Green"/>
</Info>
<Title>Test Document</Title>
<Section>
<Paragraph>
 This is regular text for these product: <Name/>
 <Profile>
  <ProfileInfo Name="Blue"/>
   <!-- The issue here is that we cannot be sure how deep the
<Name/> element is from the <Profile> and <ProfileInfo> element -->
  This is text associated with Prod Profile: <bold><Name/></bold>
 </Profile>
 This is text after the profile that is for all Prods: <Name/>
 <Profile>
  <ProfileInfo Name="Red"/>
  <ProfileInfo Name="Green"/>
  This is text associated with Product Profile for <Name/>
 </Profile>
</Paragraph>
<Paragraph>
 This is some more text.
 <Profile>
  <ProfileInfo Name="Blue"/>
  More text associated with <Name/>
 </Profile>
</Paragraph>
</Section>
<Section>
<ProfileInfo Name="Green"/>
<Paragraph>
 This is text that goes along with this section for <Name/>
</Paragraph>
</Section>
</Root>


Expected Output:


<Title>Test Document</Title>

<Section>
<Paragraph>
This is regular text for these products: Red, Blue, Green

<Profile>
 This is text associated with Product Profile for <bold>Blue</bold>
</Profile>

This is text after the profile that is for all products: Red, Blue, Green
<Profile>
 This is text associated with Product Profile for Red, Green
</Profile>

</Paragraph>

<Paragraph>
This is some more text.

<Profile>
  More text associated with Blue
</Profile>

</Paragraph>
</Section>

<Section>
<Profile>
This is text that goes along with this section for Green
</Profile>
</Section>

Ok, so the rules that we want to abide by are as follows: (The only
template that I am having trouble with is the <Name> tag, I can
correctly I identify and resolve all other tags)

1) If there is a <Name/> Element within a <Profile> element, then
take all the ProfileInfo elements that are children of the <Profile>
element and display their @Name attribute uniquely and separated by
commas.
2) If there is a <Name/> Element within a <Section> element, and the
<Section> has a <ProfileInfo> in it (the ProfileInfo will have to come
directly after the <Section> element defined by the schema.) then
output only the @Name of the <ProfileInfo>(s) associated with that
particular <Section>
3) If there is a <Name/> Element that does not reside in a <Profile>
element (which has a profile element) or within a <Section> element
that is profiled (has a <ProfileInfo> tag) then we want to output all
Prod/@name separated by commas and non repeating.


The main question is: How to scope the <xsl:key>'s when I'm in the <xsl:for-each> such that only the profiles of that specific section are looked at, not the entire document which is happening here.

Here's what I have: (My namespace is _ for convenience)

<xsl:key name="distinct-name" match="_:Prod" use="@name" />
<xsl:key name="distinct-name-profiled" match="_:ProfileInfo" use="@Name" />

<xsl:template match="_:Name">
<xsl:choose>
 <xsl:when test="ancestor::_:ProductProfile">

   <xsl:for-each
select="preceding::_:ProfileInfo[generate-id(.)=generate-id(key('distinct-name-profiled',@Name)[1])]">
    <span>
     <xsl:value-of select="@Name"/>
     <xsl:if test="position() != last()">, </xsl:if>
    </span>
    </xsl:for-each>

 </xsl:when>
 <xsl:when test="not(ancestor::_:ProductProfile) and preceding::_:Section">

   <xsl:for-each
select="preceding::_:ProfileInfo[generate-id()=generate-id(key('distinct-name-profiled',@Name)[1])]">
    <span>
     <xsl:value-of select="@Name"/>
     <xsl:if test="position() != last()">, </xsl:if>
    </span>
    </xsl:for-each>

 </xsl:when>
 <xsl:otherwise>

  <xsl:for-each
select="//_:Prod[generate-id()=generate-id(key('distinct-name',@name))]">
   <span>
    <xsl:value-of select="@name"/>
    <xsl:if test="position() != last()">, </xsl:if>
   </span>
   </xsl:for-each>

 </xsl:otherwise>
</xsl:choose>

</xsl:template>

Please let me know if there is anything else that you man need.

Thanks again for all your time,
-Ty

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Cast Your Vote

We need your help – Vote for DataDirect XML Products!

  • Best SOA or XML site

Winners and finalists announced at SOA World Conference in November.

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2007 All Rights Reserved.