0

Hello I have the following code:

<xsl:variable name="walkins" as="element()*">
   <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin1'],' ','')"/></Item>
   <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin2'],' ','')"/></Item>
   <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin3'],' ','')"/></Item>
   <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin4'],' ','')"/></Item>
   <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin5'],' ','')"/></Item>
   <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin6'],' ','')"/></Item>
   <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin7'],' ','')"/></Item>
   <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin8'],' ','')"/></Item>
</xsl:variable> 

I want to loop through 'walkins' and get all the distinct values only and those that contains characters 'abc'. I got the contains() part. It's just I don't know how to get only the distinct-values

It is also worth noting that all of these is in the same xml file.

I have tried calling it this way but I get blank:

<xsl:template match="/">
<walkins>
   <Item>
     <xsl:for-each select="distinct-values($walkins)">
      <xsl:if test="contains($walkins, 'AP')">
          <xsl:value-of select="$walkins"/>
      </xsl:if>
     </xsl:for-each>
   </Item>
</walkins>
</xsl:template>

Am I doing this right?

EDIT3::

Here is full xml file sample

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes" />
        <!--Section (1) Values here are taken from db/application and given unique names i.e. First Parameter is name Walkin1, etc-->
        <Parameters>
            <Parameter name="Walkin1" title="Walk-in 1" description="" value="" type="text" level="item" />
            <Parameter name="Walkin2" title="Walk-in 2" description="" value="" type="text" level="item" />
            <Parameter name="Walkin3" title="Walk-in 3" description="" value="" type="text" level="item" />
            <Parameter name="Walkin4" title="Walk-in 4" description="" value="" type="text" level="item" />
            <Parameter name="Walkin5" title="Walk-in 5" description="" value="" type="text" level="item" />
            <Parameter name="Walkin6" title="Walk-in 6" description="" value="" type="text" level="item" />
            <Parameter name="Walkin7" title="Walk-in 7" description="" value="" type="text" level="item" />
            <Parameter name="Walkin8" title="Walk-in 8" description="" value="" type="text" level="item" />
            <Parameter name="extraParameter1" title="Extra Parameter 1" description="" value="" type="text" level="item" />
            <Parameter name="extraParameter2" title="Extra Parameter 2" description="" value="" type="text" level="item" />
        </Parameters>
        <!--Section (2) After values are taken from application/db and assigned in section above, below is sample xml input on how it is read/called hence see section 3-->
        <Page>
          <Items>
            <Item>
              <Parameters>
                <Parameter name="Walkin1">[Data FROM db TO Here]</Parameter>
                <Parameter name="Walkin2">[Data FROM db TO Here]</Parameter>
                <Parameter name="Walkin3">[Data FROM db TO Here]</Parameter>
                <Parameter name="Walkin4">[Data FROM db TO Here]</Parameter>
                <Parameter name="Walkin5">[Data FROM db TO Here]</Parameter>
                <Parameter name="Walkin6">[Data FROM db TO Here]</Parameter>
                <Parameter name="Walkin7">[Data FROM db TO Here]</Parameter>
                <Parameter name="Walkin8">[Data FROM db TO Here]</Parameter>
                <Parameter name="extraParameter1">[Data FROM db TO Here]</Parameter>
                <Parameter name="extraParameter1">[Data FROM db TO Here]</Parameter>
              </Parameters>
            </Item>
          </Items>
        </Page>
    
        <!-- Global Parameters (Unnecessary Please Ignore) -->
          <xsl:param name="ThemeFolder" select="'/webApplicationFolder/Themes/Default'" />
          <xsl:param name="ContentFolder" select="'/webApplicationFolder/folder/'" />
    
        <xsl:template match="/">
            <xsl:element name="link">
              <xsl:attribute name="type">text/css</xsl:attribute>
              <xsl:attribute name="rel">stylesheet</xsl:attribute>
              <xsl:attribute name="href">
                <xsl:value-of select="$ContentFolder2" />/folder/css/bootstrap.min.css</xsl:attribute>
            </xsl:element>
            <xsl:element name="style">
              <xsl:attribute name="type">text/css</xsl:attribute>
                /*some css*/
            </xsl:element>
            <!--Section (3) Individual parameters are called in select as such 
            i.e. /Page/Items/Parameters/Parameter[@name='Walkin1'] 
            therefore I have tried to assign all necessary parameters or only parameters I need into a variable-->
            <div class="main">Header
                <xsl:variable name="walkins" as="element()*">
                    <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin1'],' ','')"/></Item>
                    <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin2'],' ','')"/></Item>
                    <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin3'],' ','')"/></Item>
                    <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin4'],' ','')"/></Item>
                    <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin5'],' ','')"/></Item>
                    <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin6'],' ','')"/></Item>
                    <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin7'],' ','')"/></Item>
                    <Item><xsl:value-of select="translate(/Page/Items/Item/Parameters/Parameter[@name='Walkin8'],' ','')"/></Item>
                </xsl:variable>
                <!--Section (4) In this section, I am iterating through each value of the walkins variable.
                The Problem is some parameters from application/db being passed have some duplicates.
                I want to elimate all those duplicates first and then check for contains() function
                before displaying it on to the page-->
                <div class="container">List
                    <xsl:for-each select="distinct-values($walkins[contains(.,'AP')])">
                        <xsl:value-of select="$walkins"/>
                    </xsl:for-each>
                </div>
            </div>
        </xsl:template>
    </xsl:stylesheet>

Basically, I want page to display as follows:

Header
List
<distinct-value1>
<distinct-value2>
<distinct-value3>...

How best could I achieve this?

JZnrgn
  • 41
  • 5

1 Answers1

1

In XSLT 2.0 or higher, the expression:

distinct-values($walkins)

will return a sequence of unique values (as strings) contained in your variable.

If you want to include only values that contain a substring, use a predicate:

distinct-values($walkins[contains(., 'AP')])

P.S. Surely there must be a more elegant way to construct that variable?

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Hello again Michael! :D I have edited my original question. Am I wrong with the way I am calling the variable? Because I am getting blank result. I am not really sure how to make the array variable. I am just following whatever information I could find off the web hoping one might fit my needs. – JZnrgn Jul 13 '23 at 02:15
  • I cannot help you any further without a [mcve]. That means an example of your XML input, an executable XSLT stylesheet and the expected output - all reduced to the minimum necessary to demonstrate the problem. Please edit your question and add them there. – michael.hor257k Jul 13 '23 at 02:19
  • Hello Michael, I have included full xml file in the edit. Will this be sufficient? – JZnrgn Jul 13 '23 at 03:03
  • No, I am afraid that makes no sense to me. It seems you have injected your XML input into your XSLT stylesheet. And the expected output is not clear - please post the **exact** and full HTML code you want to get. Also please clarify which processor are you using. – michael.hor257k Jul 13 '23 at 03:23
  • Hello Michael, I have edited the xml on the question. The expected output is as posited in the question. It is just to display those distinct values onto the page. For the processor, I am not sure, but it is a propriety web application I am tasked to work on. I have no core code of it. Just configurations such as these display-onto-page. So, it reads these xml files which mostly just displays elements onto the screen. If it makes sense? Basically I am just rearranging/beautifying the elements inside the page. – JZnrgn Jul 13 '23 at 04:00
  • addendum: the parameters are taken by the web app from its own db – JZnrgn Jul 13 '23 at 04:01
  • 1
    I suggest you start by identifying the processor as explained here: https://stackoverflow.com/a/25245033/3016153. Then get the raw XML input by using a stylesheet with only the [identity transform template](https://en.wikipedia.org/wiki/Identity_transform#Using_XSLT). What you're showing now makes absolutely no sense: if all the required data is hard-coded into the XSLT stylesheet, then you can just hard-code it the way you want it at the end, with no need for any transformation. – michael.hor257k Jul 13 '23 at 05:39
  • Hello Michael, took a while because i keep getting blank screen but finally got to see it. so i followed the explicit identity transform template and the result were as displayed on the full xml code [i.e. as follows: `sample1sample2` Also, the vendor is Microsoft and version is 1. – JZnrgn Jul 17 '23 at 05:00
  • I think the confusion is due to the fact that the values of the input have different names. So what I was trying to do with this stylesheet is firstly, to group same named parameters i.e. all Walkins(there are also other parameters in the original code). And then from that, Is to display onto page only those that are distinct and contains specific prefix chars i.e. 'abc'. – JZnrgn Jul 17 '23 at 05:02
  • 1
    The `parameter`elements in your input do not have any names, so I am not sure what you refer to by "Walkins". Moreover (and perhaps even more importantly), the `distinct-values()` function requires a processor that supports at least XSLT 2.0. In XSLT 1.0 you need to use the Muenchian grouping method in order to remove duplicates. – michael.hor257k Jul 17 '23 at 05:14
  • Hello Michael, what if I try to assign the specific parameters/values onto result tree fragment first? can I use meunchian grouping in rtf? – JZnrgn Jul 17 '23 at 05:28
  • You can convert the RTF to a node-set, then do anything with it. But I am completely lost regarding the purpose of this exercise. Normally XSLT is used to transform the data in the XML input. You seem to have an additional source of information. – michael.hor257k Jul 17 '23 at 06:14
  • Hello Michael, I have edited the full xml file and included descriptions if it helps better understand my problem? – JZnrgn Jul 17 '23 at 08:00
  • I am afraid it still makes no sense to me. The only way that the XSLT standard provides to pass additional data to the stylesheet is through global `xsl:param` elements. What you describe is not a standard XSL transformation and I am not sure how it works. Possibly you could process the inner `Parameter` elements by referring to them as `document('')/xsl:stylesheet/Parameters/Parameter` - but that too is illegal in standard XSLT, unless the inner elements are in a namespace. So I am afraid I don't know how to help you with this. – michael.hor257k Jul 17 '23 at 10:02