Search

Hi,

I'm in need of a little help on how best to set up data sources for the following case scenario.

Section 1 - Offices: * name * address line 1 * address line 2 * town * postcode * region

Section 2 - Products: * product name * product type * SBL pointing to office name in Section 1

What I need to do is display a list of offices each with their associated products on one page and a list of products sorted by region in which they are produced on another.

I realise I may need to modify the sections but I think this was the most logical way to set it up to avoid repetition.

I'm having a hard time trying to get my head around data source chaining to simply output the first page, let alone the second one as it seems impossible without repeating the 'region' in the Products section. However, since each office is already associated with a region, it seems like a waste of space.

Thanks in advance for any help.

display a list of offices each with their associated products on one page

1_ Do you have to display ALL offices on same page?

list of products sorted by region in which they are produced on another

2_ Do you have to display ALL products on the same page (different than previous)?

btw: what's the name of the SBL field?

1_ No. Offices by town

2_ Yes. List of regions and sublist of products. Being able to display just 1 region via url param would be a bonus

One at a time:

1_ What's the name of the page?

1_ offices url is /offices/{$region}/{$town}/ ($town is optional)

The SBL is named associated-office

For 1_

Datasource 1:

Name: Offices by town
Source: Section 1
Filter by Name with value {$town}
Filter by Region with value {$region}
Output parameter: Name
Included Elements: name, region + others if you need them

It will add the parameter $ds-offices-by-town to the param pool to be used with other datasources or anywhere else in the system.

Datasource 2:

Name: Products by town
Source: Section 2
Filter by Associated office value {$ds-offices-by-town}
Included Elements: product name, product type

DS2 uses the output from DS1 to filter the results.

On accessing example.com/offices/france/paris DS1 will return all offices located in Paris, France and DS2 will return all the products for every office returned by DS1.

I think this should work. I'm not 100% sure in the situation where you have more than 1 office in a town. Please tell me if the resulting XML contains all offices from that town or only the first office.

For example 2 offices with town Paris in region France. They should both appear in frontend with their products.

Genius! Fortunately there is never more than 1 office per town so I won't have that problem.

Can you wrap your head around #2?

Glad it helped you. I'm preparing for 2_ so until then, just for the sake of knowledge, could you please enter another office in the same town? I'm REALLY curious if it works for more than 1 entry.

Yup, several offices in 1 town all appear. Only downside of course is the products are not associated with each office so the only way to display them accordingly would be the call the value of the SBL for each and sort with XSLT

the only way to display them accordingly would be the call the value of the SBL for each and sort with XSLT

Of course ;)

For 2_ I would create another section containing the names of the regions and change the region field in Section 1 to Select Box with dynamic options pointing to Section 3 -> Name.

This way, you can create DS1 which extracts the names of the regions, DS2 extracts all the offices with their names and regions and DS3 which extracts all products. They will all be mixed up together using XSLT.

DS1:

Name: All Regions
Source: Section 3
Included Elements: name

It outputs the names of all regions.

DS2:

Name: All Offices
Source: Section 1
Included Elements: name, region

It outputs all the offices with their region.

DS3:

Name: All Products
Source: Section 2
Included Elements: product name, product type, associated office

It outputs all the products.

<xsl:for-each select="all-regions/entry/name">
    <xsl:value-of select="." />
    <xsl:apply-templates select="/data/all-offices/entry[region/@handle = @handle ]" />
</xsl:for-each

<xsl:template match="all-offices/entry">
    <xsl:apply-templates select="/data/all-products/entry[associated-office/@handle = name]
</xsl:template>

<xsl:template match="all-products/entry">
    <xsl:value-of select="name" />
</xsl:template>

Sorry for the dealy. Back on it now!

I've set up all the DSs but I'm having trouble calling the template. It's just not being picked up and the default XSLT behaviors kick in instead.

This is the XML

    <products>
    <section id="10" handle="products">Products</section>
    <entry id="42">
        <associated-office>
            <item id="43" handle="bolton-office" section-handle="offices" section-name="Offices">Bolton office</item>
        </associated-office>
        <name handle="pastures">Pastures</name>
    </entry>
</products>
<offices>
    <section id="9" handle="offices">Offices</section>
    <entry id="46">
        <office-name handle="bolton-office">Bolton office</office-name>
        <county handle="lancashire">Lancashire</county>
        <region>
            <item handle="north-west">North-West</item>
        </region>
    </entry>
</offices>
<regions>
    <section id="14" handle="regions">Regions</section>
    <entry id="78">
        <region handle="north-west">North-West</region>
    </entry>
</region>

and the templates

    <xsl:for-each select="regions/entry/region">
    <h2 id="{@handle}"><xsl:value-of select="." /></h2>

    <xsl:apply-templates select="/data/offices/entry/region/item[text() = .]" />

</xsl:for-each>

<xsl:template match="offices/entry">
    <xsl:value-of select="." /> 
    <xsl:apply-templates select="/data/products/entry/associated-office/item[@handle = office-name/@handle]" />
</xsl:template>

Base rule. In predicates '[...]' always use the handles. That's their purpose.

On line 4

<xsl:apply-templates select="/data/offices/entry/region/item[text() = .]" />

you must match all offices/entry with a certain property so change it to

<xsl:apply-templates select="/data/offices/entry[region/item/@handle = @handle]" />

I changed the place of the bracket [.

On line 10 aswell

 <xsl:apply-templates select="/data/products/entry/associated-office/item[@handle = office-name/@handle]" />

You want to select all prodcuts/entry with the office name equal to whatever.

 <xsl:apply-templates select="/data/products/entry[associated-office/item/@handle = office-name/@handle]" />

I'm afraid that returns nothing :(

You should try and debug. Go step by step, use <xsl:value-of select="..." /> and make sure you are navigating the right way.

I can't tell where the problem is. It's pretty hard to "guess" it.

EDIT to correct version

This is how I see your templates. If they are not working, then start debugging.

<xsl:for-each select="regions/entry/region">
   <h2 id="{@handle}"><xsl:value-of select="." /></h2>
   <xsl:apply-templates select="/data/offices/entry[region/item/@handle = current()/@handle]" />
</xsl:for-each>

<xsl:template match="offices/entry">
    <xsl:value-of select="office-name" />
    <xsl:apply-templates select="/data/products/entry[associated-office/item/@handle = office-name/@handle]" />
</xsl:template>

<xsl:template match="products/entry">
    <xsl:value-of select="name" />
</xsl:template>

Yep, that's exactly what my templates look like but they return nothing.

I have no idea where to go with this now, can anyone else help?

vladG, thanks for all your help with this.

It appears all I needed was to use

[region/item/@handle = current()/@handle]

instead of

[region/item/@handle = @handle]

Again, many thanks.

Glad to help.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details