Home > database >  how to use Parameter in XSL and count() correctly to get data from xml
how to use Parameter in XSL and count() correctly to get data from xml

Time:12-10

  1. I am trying the following to pass a parameter by the state code and get the details for the orders based on state and the count of number of orders I tried the following code but I am not able to make the parameter work in xsl.
  2. Example I want to pass the parameter as getState=TX (where getState is the parameter name) and it should only get me the corresponding data of TX and the same applies to MO and CA. I'm limited to Xsl 1.0 also I am able to get the count but its printing outside the element I need it like this <state name="TX" count "2">
  3. The state has to be passed as a code only meaning TX,CA,MO (as a parameter not the full name) java -jar saxon-he-10.5.jar -xsl:walmart.xsl -s:orders.xml -o:testoutput.xml getState=TX -> can anyone please confirm is this how its supposed to be passed while generating the output file?
  4. Output what I have currently looks like this it is sorted in descending based order of date. Can anyone please advice how the above can be achieved(count and parameter).

The current output file looks as below

<?xml version="1.0" encoding="UTF-8"?>
<details>
   <state name="TX">count:2
   <order date="2021-08-15"
             item="onions"
             address="amway avenue"
             phone="(432) 666-7890"
             inventory="9976454"/>
   <order date="2021-10-11"
             item="cereal"
             address="34 main st"
             phone="(212) 566-7670"
             inventory="0247556"/>
   </state>
   <state name="CA">count:2
   <order date="2021-02-19"
             item="eggs"
             address="Audobon st"
             phone="(232) 456-3211"
             inventory="0244559"/>
   <order date="2021-05-13"
             item="brocolli"
             address="47 apartment"
             phone="(444) 564-3433"
             inventory="3434654"/>
   </state>
   <state name="MO">count:2
   <order date="2021-02-27"
             item="fries"
             address="paseo blvd"
             phone="(309) 123-5644"
             inventory="2245526"/>
   <order date="2021-12-04"
             item="juice"
             address="locust st"
             phone="(309) 566-5555"
             inventory="2245556"/>
   </state>
</details>

walmart.xsl this is my xsl file which I tried

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:param name="getState" select="response/walmart"/>
    <xsl:template match="/">
        <xsl:element name="details">
            <state name="TX">
        count:<xsl:value-of select= "count(response/walmart[state = 'TX'])"/>
                <xsl:apply-templates select="response/walmart[state = 'TX']">
                    <xsl:sort select="order_date" order="ascending"/>
                </xsl:apply-templates>
            </state>
            <state name="CA">
        count: <xsl:value-of select= "count(response/walmart[state = 'CA'])"/>
                <xsl:apply-templates select="response/walmart[state = 'CA']">
                    <xsl:sort select="order_date" order="ascending"/>
                </xsl:apply-templates>
            </state>
            <state name="MO">
        count:<xsl:value-of select= "count(response/walmart[state = 'MO'])"/>
                <xsl:apply-templates select="response/walmart[state = 'MO']">
                    <xsl:sort select="order_date" order="ascending"/>
                </xsl:apply-templates>
            </state>
        </xsl:element>
    </xsl:template>
    <xsl:template match="walmart">
        <order date="{order_date}" item="{item}" address="{walmart_address}" phone ="{walmart_contact_phone}" inventory="{inventory_number}" >
        </order>
    </xsl:template>
</xsl:stylesheet>

this is the xml file to pull data orders.xml

<?xml version="1.0"?>
<response>
    <walmart>
        <order_date>2021-10-11</order_date>
        <item>cereal</item>
        <state>TX</state>
        <walmart_address>34 main st</walmart_address>
        <walmart_contact_phone>(212) 566-7670</walmart_contact_phone>
        <inventory_number>0247556</inventory_number>
    </walmart>
    <walmart>
        <order_date>2021-05-13</order_date>
        <item>brocolli</item>
        <state>CA</state>
        <walmart_address>47 apartment</walmart_address>
        <walmart_contact_phone>(444) 564-3433</walmart_contact_phone>
        <inventory_number>3434654</inventory_number>
    </walmart>
    <walmart>
        <order_date>2021-08-15</order_date>
        <item>onions</item>
        <state>TX</state>
        <walmart_address>amway avenue</walmart_address>
        <walmart_contact_phone>(432) 666-7890</walmart_contact_phone>
        <inventory_number>9976454</inventory_number>
    </walmart>
    <walmart>
        <order_date>2021-02-19</order_date>
        <item>eggs</item>
        <state>CA</state>
        <walmart_address>Audobon st</walmart_address>
        <walmart_contact_phone>(232) 456-3211</walmart_contact_phone>
        <inventory_number>0244559</inventory_number>
    </walmart>
    <walmart>
        <order_date>2021-12-04</order_date>
        <item>juice</item>
        <state>MO</state>
        <walmart_address>locust st</walmart_address>
        <walmart_contact_phone>(309) 566-5555</walmart_contact_phone>
        <inventory_number>2245556</inventory_number>
    </walmart>
    <walmart>
        <order_date>2021-02-27</order_date>
        <item>fries</item>
        <state>MO</state>
        <walmart_address>paseo blvd</walmart_address>
        <walmart_contact_phone>(309) 123-5644</walmart_contact_phone>
        <inventory_number>2245526</inventory_number>
    </walmart>
</response>

Any inputs to make the code better and suggestions are much appreciated.

CodePudding user response:

I believe the smart thing to do here would be:

  1. use a key to select the data by state; and
  2. put the selected data in a variable so that you can use a single selection for both counting the selected data and outputting it.

Then you could do simply:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:param name="getState"/>

<xsl:key name="data-by-state" match="walmart" use="state" />

<xsl:template match="/response">
    <xsl:variable name="state-data" select="key('data-by-state', $getState)" />
    <details>
        <state name="{$getState}" count="{count($state-data)}">
            <xsl:for-each select="$state-data">
                <xsl:sort select="order_date"/>
                <order date="{order_date}" item="{item}" address="{walmart_address}" phone ="{walmart_contact_phone}" inventory="{inventory_number}" />
            </xsl:for-each>
        </state>
    </details>
</xsl:template>

</xsl:stylesheet>

When this stylesheet is called with a parameter getState="TX" the result will be:

<?xml version="1.0" encoding="UTF-8"?>
<details>
  <state name="TX" count="2">
    <order date="2021-08-15" item="onions" address="amway avenue" phone="(432) 666-7890" inventory="9976454"/>
    <order date="2021-10-11" item="cereal" address="34 main st" phone="(212) 566-7670" inventory="0247556"/>
  </state>
</details>

CodePudding user response:

You want something like this

<xsl:template match="/">
  <details>
    <xsl:variable name="selection" 
                  select="response/walmart[state=$getState]"/>
    <state name="{$getState}" count="{count($selection)}">
      <xsl:apply-templates select="$selection">
        <xsl:sort select="order_date" order="ascending"/>
      </xsl:apply-templates>    
    </state>
  </details>
</xsl:template>

<xsl:template match="walmart">
  <order date="{order_date}" 
         item="{item}" 
         address="{walmart_address}" 
         phone="{walmart_contact_phone}" 
         inventory="{inventory_number}" />
  <order>
</xsl:template>
  
  • Related