Home > Back-end >  Xslt how to remove element where its value is equals something with | operation?
Xslt how to remove element where its value is equals something with | operation?

Time:10-01

I would like to remove <Status> tag from <Data> when its value is not either S01, or S03 for example. I have tried using | statement in the match condition but it dos not return result as what I expected.

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" TimeStamp="2021-09-30T14:47:21.6130539 07:00" Version="16.1" xmlns="http://localhost">
  <Class ClassShortName="CLA-001" />
  <Student>
    <BirthPlace>
      <Province CodeContext="3">K013</Province>
      <Distance>9006</Distance>
      <Zone CodeContext="3">PNH</Zone>
    </BirthPlace>
    <Data>
      <Status RepeatIndex="1" CodeContext="0">S01</Status>
      <Time RepeatIndex="1" TimeType="001">2017-10-02T02:45:00Z</Time>
    </Data>
  </Student>
    <Student>
    <BirthPlace>
      <Province CodeContext="3">K009</Province>
      <Distance>9006</Distance>
      <Zone CodeContext="3">PNH</Zone>
    </BirthPlace>
    <Data>
      <Status RepeatIndex="1" CodeContext="0">S02</Status>
      <Time RepeatIndex="1" TimeType="001">2020-12-13T07:00:00Z</Time>
    </Data>
  </Student>
    <Student>
    <BirthPlace>
      <Province CodeContext="3">K002</Province>
      <Distance>9006</Distance>
      <Zone CodeContext="3">PNH</Zone>
    </BirthPlace>
    <Data>
      <Status RepeatIndex="1" CodeContext="0">S03</Status>
      <Time RepeatIndex="1" TimeType="001">2016-08-22T23:21:00Z</Time>
    </Data>
  </Student>
</root>

Here is my XSLT file

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
                xmlns:ns0="http://localhost"
                xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="ns0:root">
    <xsl:variable name="condition" select="ns0:Student[ns0:BirthPlace/ns0:Zone='PNH']" />
    <xsl:if test="$condition">
      <xsl:copy>
        <xsl:copy-of select="@* | ns0:Class "/>
        <xsl:apply-templates select="$condition"/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>


  <xsl:template match="ns0:Student">
    <xsl:copy>
      <xsl:apply-templates select="ns0:BirthPlace|ns0:Data"/>
    </xsl:copy>
  </xsl:template>


  <xsl:template match="ns0:BirthPlace">
    <xsl:copy>
      <xsl:copy-of select="ns0:Province|ns0:Distance"/>
    </xsl:copy>
  </xsl:template>



  <xsl:template match="ns0:Data">
    <xsl:copy>
      <xsl:apply-templates select="ns0:Time|ns0:Status"/>
    </xsl:copy>
  </xsl:template>
  


  <xsl:template match="ns0:Time">
    <xsl:copy>
      <xsl:copy-of select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="ns0:Status">
    <xsl:copy>
      <xsl:copy-of select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="ns0:Data[ns0:Status!='S01']|ns0:Data[ns0:Status!='S03']"/>
  

</xsl:stylesheet>

Below is result I would like to get

<root xmlns="http://localhost"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      TimeStamp="2021-09-30T14:47:21.6130539 07:00"
      Version="16.1">
   <Class ClassShortName="CLA-001"/>
   <Student>
      <BirthPlace>
         <Province CodeContext="3">K013</Province>
         <Distance>9006</Distance>
      </BirthPlace>
      <Data>
        <Status RepeatIndex="1" CodeContext="0">S01</Status>
        <Time RepeatIndex="1" TimeType="001">2017-10-02T02:45:00Z</Time>
    </Data>
   </Student>
   <Student>
      <BirthPlace>
         <Province CodeContext="3">K009</Province>
         <Distance>9006</Distance>
      </BirthPlace>
    <Data>
      <Time RepeatIndex="1" TimeType="001">2020-12-13T07:00:00Z</Time>
    </Data>      
   </Student>
   <Student>
      <BirthPlace>
         <Province CodeContext="3">K002</Province>
         <Distance>9006</Distance>
      </BirthPlace>
      <Data>
        <Status RepeatIndex="1" CodeContext="0">S03</Status>
        <Time RepeatIndex="1" TimeType="001">2016-08-22T23:21:00Z</Time>
      </Data>      
   </Student>
</root>

Would you mind to guide me, how could I get the result as expected?

Best regards,

Veasna

CodePudding user response:

I would like to remove <Status> tag from <Data> when its value is not either S01, or S03

I believe all you need for this is:

<xsl:template match="ns0:Status[not(.='S01' or .='S03')]"/>

See the demo here: https://xsltfiddle.liberty-development.net/gVAkJ5e

CodePudding user response:

I think these should do it:

  <xsl:template match="ns0:Status[(. = 'S01') or (. = 'S03')]">
    <xsl:copy>
      <xsl:copy-of select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="ns0:Status"/>

CodePudding user response:

Your requirement says "when its value is not either S01, or S03" but your code says "when it is not S01 or not S03". If you think about it, if it only has one value, then that value will either be not S01, or it will be not S03 (or both). Rather than (. != 'S01' or . != 'S03'), you want not(. = 'S01' or . = 'S03').

  • Related