开发者

Conditional Statements in XSLT when having to choose a tag from several elements

开发者 https://www.devze.com 2023-03-09 11:47 出处:网络
I am relatively new to XSLT but am trying to learn it to provide a solution for a client. Although the ultimate aim is to write an XSLT for Filemaker Pro, I would like to first get the HTML one right.

I am relatively new to XSLT but am trying to learn it to provide a solution for a client. Although the ultimate aim is to write an XSLT for Filemaker Pro, I would like to first get the HTML one right.

I receive a generated XML file which contains booking information for tours. The informatio it contains as well as the number of orders also varies.

The XSLT is needed to present all the XML info in a more presentable table form.

My problems begin when I put in the conditional statements. In the example if the value of BSServType='TUTU', the table should reflect some information, otherwise it should look for the value 'SOHO' and if not 'SOVI'.

This particular tag is itself a child of DetSeg. There are several DetSeg tags. Unfortunately, the info may be in any 1 tag so the XSLT should be capable of looking into the right one and then choosing one of the values. I have not been able to do so.

The second problem is the statement that follows: when the value is 'TUTU', select 'BSServDest' seems to be working fine as it is a sibling to 'BSServType' but 'BSServQuota' is not a sibling but rather a 'nephew' if I can say so. This also is posing a problem as I am unable to select them

I hope I have been clear enough in my explainations. The XML as well as the XSLT have been pasted. I have tried looking arounf the site to seeif the problem has already been presented but have nout found anything to help me completely. I hope this problem can be solved as there are several more conditional statements that I will have to write all following the same logic.

Another doubt I have: is it asy to adapt th XSLT that I amwriting for Filemaker Pro later?

Thanking everyone in advance.

The XML code:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="order.xsl" type="text/xsl" ?>
<AllBookingFnp>
<BookingFnp>
<BookSegServ>
<BookSeg>
<DetSeg>
<BSDataIni>2011-06-25</BSDataIni>
<BSDataFin>2011-07-02</BSDataFin>
<BSCodTGeogr>LOC</BSCodTGeogr>
<BSCodCGeogr>ATH</BSCodCGeogr>
<BSDesGeogr><![CDATA[ATENE]]></BSDesGeogr>
<BSServType>TUTU</BSServType>
<BSServCod>GREMETEORE</BSServCod>
<BSServDes><![CDATA[TOUR GRECIA CLASSICA E METEORE]]></BSServDes>
<BSServTimeIni></BSServTimeIni>
<BSServDest>GRECIT</BSServDest>
</DetSeg>
<BSSservSpec>
<BSservQtall>1</BSservQtall>
<BSServQuota>DBLCDM</BSServQuota>
<BSServCodSist>DBL</BSServCodSist>
<BSServCodTrat>CDM</BSServCodTrat>
<BSServSist><![CDATA[DOPPIA]]></BSServSist>
<BSservTrat><![CDATA[COME DA PROGRAMMA]]></BSservTrat>
</BSSservSpec>
<BSFornText>SERVIZIO FORNITO DA:</BSFornText>
<BSFornDescr><![CDATA[PANHELLAS]]></BSFornDescr>
<BSFornInd><![CDATA[EL.VENIZELOU 161 N.ERYTHREA 14671]]></BSFornInd>
<BSFornLoc><![CDATA[ATHENS]]></BSFornLoc>
<BSFornTel>0030 210 8003073</BSFornTel>
<BSFornFax>Fax 8003030</BSFornFax>
</BookSeg>
<BookSeg>
<DetSeg>
<BSDataIni>2011-07-02</BSDataIni>
<BSDataFin>2011-07-09</BSDataFin>
<BSCodTGeogr>LOC</BSCodTGeogr>
<BSCodCGeogr>HYDV</BSCodCGeogr>
<BSDesGeogr><![CDATA[HYDRA - GRECIA]]></BSDesGeogr>
<BSServType>SOVI</BSServType>
<BSServCod>GREHYDRABEAC</BSServCod>
<BSServDes><![CDATA[HYDRA BEACH - VILLAGGIO VALTUR]]></BSServDes>
<BSServTimeIni></BSServTimeIni>
<BSServDest>GRECIA</BSServDest>
</DetSeg>
<BSSservSpec>
<BSservQtall>1</BSservQtall>
<BSServQuota>DBOCLAFV</BSServQuota>
<BSServCodSist>DBOCLA</BSServCodSist>
<BSServCodTrat>FV</BSServCodTrat>
<BSServSist><![CDATA[DOPPIA+letto uso doppia CLASSIC]]></BSServSist>
<BSservTrat><![CDATA[]]></BSservTrat>
</BSSservSpec>
<BSAnagRis>
<BSAnagDesRis><![CDATA[]]></BSAnagDesRis>
<BSAnagIndRis><![CDATA[A.E. PLEPI-THERMISIA]]></BSAnagIndRis>
<BSAnagLocRis><![CDATA[ERMIONI]]></BSAnagLocRis>
<BSAnagTelRis></BSAnagTelRis>
<BSAnagFaxRis></BSAnagFaxRis>
</BSAnagRis>
<BSServNoteDet><![CDATA[NOTA BENE: ALL'ARRIVO GLI OSPITI CHE NON UTILIZZANO I TRASPORTI VALTUR]]></BSServNoteDet>
<BSServNoteDet><![CDATA[SONO ATTESI DOPO LE ORE 16:00. IL GIORNO DELLA VOSTRA PARTENZA VI]]></BSServNoteDet>
<BSServNoteDet><![CDATA[INVITIAMO A LIBERARE LE STANZE PRIMA DELLE ORE 10:00.]]></BSServNoteDet>
<BSServNoteDet><![CDATA[**********************************************************************]]></BSServNoteDet>
<BSFornInd><![CDATA[]]></BSFornInd>
<BSFornLoc><![CDATA[]]></BSFornLoc>
<BSFornTel></BSFornTel>
<BSFornFax></BSFornFax>
</BookSeg>
</BookSegServ>
</BookingFnp>
<BookingFnp>
<BookSegServ>
<BookSeg>
<DetSeg>
<BSDataIni>2011-06-25</BSDataIni>
<BSDataFin>2011-06-25</BSDataFin>
<BSServType>TFTI</BSServType>
<BSServCod>NYCAPTHTL-I</BSServCod>
<BSServDes><![CDATA[TRANSFER APT NEW YORK-HOTEL]]></BSServDes>
<BSServTimeIni></BSServTimeIni>
<BSServDest>USA</BSServDest>
</DetSeg>
<BSSservSpec>
<BSservQtall>2</BSservQtall>
<BSServQuota></BSServQuota>
<BSServCodSist></BSServCodSist>
<BSServCodTrat></BSServCodTrat>
<BSServSist><![CDATA[]]></BSServSist>
<BSservTrat><![CDATA[]]></BSservTrat>
</BSSservSpec>
<BSServFrom><![CDATA[AZ   642 FCO-EWR 25/06/11 13:45]]></BSServFrom>
<BSServTo><![CDATA[RADISSON LEXINGTON HOTEL]]></BSServTo>
<BSFornText>SERVIZIO FORNITO DA:</BSFornText>
<BSFornDescr><![CDATA[TEAM AMERICA INC]]></BSFornDescr>
<BSFornInd><![CDATA[125 PARK AVENUE, 2ND FLOOR]]></BSFornInd>
<BSFornLoc><![CDATA[NEW YORK]]></BSFornLoc>
<BSFornTel>001 212 6977165</BSFornTel>
<BSFornFax>Fax 7182471706</BSFornFax>
</BookSeg>
<BookSeg>
<DetSeg>
<BSDataIni>2011-06-25</BSDataIni>
<BSDataFin>2011-07-02</BSDataFin>
<BSServType>SOHO</BSServType>
<BSServCod>NYCLEXINGTON</BSServCod>
<BSServDes><![CDATA[RADISSON LEXINGTON HOTEL]]></BSServDes>
<BSServTimeIni></BSServTimeIni>
<BSServDest>USA</BSServDest>
</DetSeg>
<BSSservSpec>
<BSservQtall>1</BSservQtall>
<BSServQuota>DBL</BSServQuota>
<BSServCodSist>DBL</BSServCodSist>
<BSServCodTrat></BSServCodTrat>
<BSServSist><![CDATA[DOPPIA]]></BSServSist>
<BSservTrat><![CDATA[]]></BSservTrat>
</BSSservSpec>
<BSAnagRis>
<BSAnagDesRis><![CDATA[]]></BSAnagDesRis>
<BSAnagIndRis><![CDATA[]]></BSAnagIndRis>
<BSAnagLocRis><![CDATA[NEW YORK]]></BSAnagLocRis>
<BSAnagTelRis></BSAnagTelRis>
<BSAnagFaxRis></BSAnagFaxRis>
</BSAnagRis>
<BSFornInd><![CDATA[]]></BSFornInd>
<BSFornLoc><![CDATA[]]></BSFornLoc>
<BSFornTel></BSFornTel>
<BSFornFax></BSFornFax>
</BookSeg>
<BookSeg>
<DetSeg&g开发者_StackOverflowt;
<BSDataIni>2011-06-25</BSDataIni>
<BSDataFin>2011-06-25</BSDataFin>
<BSServType>TFTI</BSServType>
<BSServCod>NYCAPTHTL-O</BSServCod>
<BSServDes><![CDATA[TRANSFER HOTEL-APT NEW YORK]]></BSServDes>
<BSServTimeIni></BSServTimeIni>
<BSServDest>USA</BSServDest>
</DetSeg>
<BSSservSpec>
<BSservQtall>2</BSservQtall>
<BSServQuota></BSServQuota>
<BSServCodSist></BSServCodSist>
<BSServCodTrat></BSServCodTrat>
<BSServSist><![CDATA[]]></BSServSist>
<BSservTrat><![CDATA[]]></BSservTrat>
</BSSservSpec>
<BSServFrom><![CDATA[AZ   642 FCO-EWR 25/06/11 13:45]]></BSServFrom>
<BSServTo><![CDATA[RADISSON LEXINGTON HOTEL]]></BSServTo>
<BSFornText>SERVIZIO FORNITO DA:</BSFornText>
<BSFornDescr><![CDATA[TEAM AMERICA INC]]></BSFornDescr>
<BSFornInd><![CDATA[125 PARK AVENUE, 2ND FLOOR]]></BSFornInd>
<BSFornLoc><![CDATA[NEW YORK]]></BSFornLoc>
<BSFornTel>001 212 6977165</BSFornTel>
<BSFornFax>Fax 7182471706</BSFornFax>
</BookSeg>
</BookSegServ>
</BookingFnp>
</AllBookingFnp>

The XSLT:`

    <?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <html>
  <body>
  <h2>Liste des commandes</h2>
  <table border="1">
    <tr bgcolor="#9acd32">
      <th>Destination</th>
      <th>BSServQuota</th>
    </tr>
    <xsl:for-each select="AllBookingFnp/BookingFnp">
    <tr>
      <xsl:choose>
      <xsl:when test="BookSegServ/BookSeg/DetSeg/BSServType='TUTU'">
      <td><xsl:value-of select="BookSegServ/BookSeg/DetSeg/BSServDest" /></td>
      <td><xsl:value-of select="BookSegServ/BookSeg/BSSservSpec/BSServQuota" /></td>
      </xsl:when>
      <xsl:when test="BookSegServ/BookSeg/DetSeg/BSServType='SOHO'">
      <td><xsl:value-of select="BookSegServ/BookSeg/DetSeg/BSServDest" /></td>
      <td><xsl:value-of select="BookSegServ/BookSeg/BSSservSpec/BSServQuota" /></td>
      </xsl:when>
      <xsl:when test="BookSegServ/BookSeg/DetSeg/BSServType='SOVI'">
      <td><xsl:value-of select="BookSegServ/BookSeg/DetSeg/BSServDest" /></td>
      <td><xsl:value-of select="BookSegServ/BookSeg/BSSservSpec/BSServQuota" /></td>
      </xsl:when>
      </xsl:choose>
    </tr>
    </xsl:for-each>
  </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

The result I am getting is the following in a table:

Destination: GRECIT USA

BSServQuota: DBLCDM -

From the XML file, the info is being taken from the first <DetSeg> from the first <BookingFnp> as it can see the info TUTU present but in the second row, it is unable to do so as the info TUTU/SOHO or SOVI is not present in the first <DetSeg> but in the second one. It is supposed to look in the second <DetSeg> and validate 'SOHO' and thus choose 'DBL' from <BSServQuota>

I would like it to look at all three <DetSeg> and look for the value 'TUTU', and if present, prsent the info I want, otherwise look for the value 'SOHO' and otherwise 'SOVI'.

Thanks.


You're falling into a trap here: you're seeing constructs like for-each and choose that look familiar from other languages, and you're instinctively using them in preference to other less familiar constructs. As a result, you're not writing your code "the XSLT way". The XSLT way is to use template rules: templates that match particular patterns occurring in the input. This is sometimes called "push processing" as distinct from "pull processing".

So this kind of code:

<xsl:choose>
      <xsl:when test="BookSegServ/BookSeg/DetSeg/BSServType='TUTU'">
      <td><xsl:value-of select="BookSegServ/BookSeg/DetSeg/BSServDest" /></td>
      <td><xsl:value-of select="BookSegServ/BookSeg/BSSservSpec/BSServQuota" /></td>

should be written like this:

<xsl:apply-templates select="BookSegServ/BookSeg"/>

<xsl:template match="BookSeg[DetSeg/BSServType='TUTU']">
  <td><xsl:value-of select="DetSeg/BSServDest"/></td>
  <td><xsl:value-of select="BSSservSpec/BSServQuota" /></td>
</xsl:template>

with further template rules that match other values of BSServType.

(I'm only trying to point you in the right direction here, not to provide working code).


I managed to get the answer and get my XSLT working. I had the help of an expert but I thought I would share the answer: Michael Kay had put me on the right track but I had been unable to do it on my own but anyway here it is:

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/AllBookingFnp">
        <html>
            <body>
                <h2>Liste des commandes</h2>
                <table border="1">
                    <tr bgcolor="#9acd32">
                        <th>Destination</th>
                        <th>BSServQuota</th>
                    </tr>
                    <xsl:apply-templates select="BookingFnp"></xsl:apply-templates>
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="BookingFnp">
                <xsl:choose>
                    <xsl:when test="BookSegServ/BookSeg/DetSeg/BSServType='TUTU'">
                        <xsl:apply-templates select="BookSegServ/BookSeg/DetSeg[BSServType='TUTU']"/>
                    </xsl:when>
                    <xsl:when test="BookSegServ/BookSeg/DetSeg/BSServType='SOHO'">
                        <xsl:apply-templates select="BookSegServ/BookSeg/DetSeg[BSServType='SOHO']"/>
                    </xsl:when>
                    <xsl:when test="BookSegServ/BookSeg/DetSeg/BSServType='SOVI'">
                        <xsl:apply-templates select="BookSegServ/BookSeg/DetSeg[BSServType='SOVI']"/>
                    </xsl:when>
                </xsl:choose>
    </xsl:template>

    <xsl:template match="DetSeg">
        <tr>
            <td><xsl:value-of select="BSServDest" /></td>
            <td><xsl:value-of select="parent::BookSeg/BSSservSpec/BSServQuota" /></td>
        </tr>
    </xsl:template>

</xsl:stylesheet>

Thanks to everyone who tried to help me.


Here you have an example solution totally template driven (no loops, no choose):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" indent="yes" omit-xml-declaration="yes" />

    <xsl:template match="/AllBookingFnp">
        <html>
            <body>
                <h2>Liste des commandes</h2>
                <table border="1">
                    <tr bgcolor="#9acd32">
                        <th>Destination</th>
                        <th>BSServQuota</th>
                    </tr>
                    <xsl:apply-templates select="BookingFnp"/>
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="BookingFnp">
        <tr>
            <xsl:apply-templates select="BookSegServ/BookSeg/DetSeg"/>
        </tr>
    </xsl:template>

    <xsl:template match="DetSeg[BSServType='TUTU']">
        <xsl:apply-templates select="BSServDest"/>
    </xsl:template>

    <xsl:template match="DetSeg[BSServType='SOHO' and 
        not(parent::BookSeg/
                    preceding-sibling::BookSeg[1]/
                        DetSeg[BSServType='TUTU'])]">
        <xsl:apply-templates select="BSServDest"/>
    </xsl:template>

    <xsl:template match="DetSeg[BSServType='SOVI' and 
        not(parent::BookSeg/
                    preceding-sibling::BookSeg/
                        DetSeg[BSServType='SOHO'] or
                parent::BookSeg/
                    preceding-sibling::BookSeg/
                        DetSeg[BSServType='TUTU']
        )]">
        <xsl:apply-templates select="BSServDest"/>
    </xsl:template>

    <xsl:template match="BSServDest">
        <td><xsl:value-of select="." /></td>
        <td><xsl:value-of select="
                parent::DetSeg/
                following-sibling::BSSservSpec/
                BSServQuota" /></td>
    </xsl:template>

    <xsl:template match="*"/>

</xsl:stylesheet>
0

精彩评论

暂无评论...
验证码 换一张
取 消