XSLT Filter Result Using XSLT Array

I am new to XSLT.

Below is the source XML that I get. The Request tag contains FlightId , which is used to filter the Result tag.

XML source:

 <Response> <Request> <RequestedFlights> <FlightId>2121</FlightId> <FlightId>2584</FlightId> </RequestedFlights> </Request> <Result> <Flights> <Flight> <Segments> <Segment> <Id>1</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>2</Id> <FlightNumber>1121</FlightNumber> </Segment> </Segments> </Flight> <Flight> <Segments> <Segment> <Id>3</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>4</Id> <FlightNumber>2584</FlightNumber> </Segment> </Segments> </Flight> <Flight> <Segments> <Segment> <Id>5</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>6</Id> <FlightNumber>2584</FlightNumber> </Segment> <Segment> <Id>7</Id> <FlightNumber>2023</FlightNumber> </Segment> </Segments> </Flight> </Flights> </Result> </Response> 

XSLT:

 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes" /> <xsl:variable name="ReqFlights" select="//Request/RequestedFlights/FlightId" /> <xsl:variable name="FilterFlights" select="//Result/Flights/Flight[Segments/Segment/FlightNumber=$ReqFlights]"/> <xsl:template match="Response"> <FilterResult> <ResultCount> <xsl:value-of select="count($FilterFlights)"/> </ResultCount> <xsl:copy> <xsl:copy-of select="$FilterFlights"/> </xsl:copy> </FilterResult> </xsl:template> </xsl:stylesheet> 

I got below output using the above XSLT.

Output:

 <FilterResult> <ResultCount>3</ResultCount> <Response> <Flight> <Segments> <Segment> <Id>1</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>2</Id> <FlightNumber>1121</FlightNumber> </Segment> </Segments> </Flight> <Flight> <Segments> <Segment> <Id>3</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>4</Id> <FlightNumber>2584</FlightNumber> </Segment> </Segments> </Flight> <Flight> <Segments> <Segment> <Id>5</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>6</Id> <FlightNumber>2584</FlightNumber> </Segment> <Segment> <Id>7</Id> <FlightNumber>2023</FlightNumber> </Segment> </Segments> </Flight> </Response> </FilterResult> 

I would like to get a lower conclusion.

Expected Result:

 <FilterResult> <ResultCount>1</ResultCount> <Response> <Flight> <Segments> <Segment> <Id>3</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>4</Id> <FlightNumber>2584</FlightNumber> </Segment> </Segments> </Flight> </Response> </FilterResult> 

Please help me. How to use an array to filter the response and get the expected result. Thanks.

+4
source share
2 answers

Using

 /*/Result/*/Flight [count(*/*)=count(/*/Request/*/FlightId) and not(*/*/FlightNumber[not(. = /*/Request/*/FlightId)]) ] 

Here is the complete conversion:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="/"> <xsl:variable name="vHits" select= "/*/Result/*/Flight [count(*/*)=count(/*/Request/*/FlightId) and not(*/*/FlightNumber[not(. = /*/Request/*/FlightId)]) ]"/> <FilterResult> <ResultCount><xsl:value-of select="count($vHits)"/></ResultCount> <Response> <xsl:copy-of select="$vHits"/> </Response> </FilterResult> </xsl:template> </xsl:stylesheet> 

When this conversion is applied to the provided XML document:

 <Response> <Request> <RequestedFlights> <FlightId>2121</FlightId> <FlightId>2584</FlightId> </RequestedFlights> </Request> <Result> <Flights> <Flight> <Segments> <Segment> <Id>1</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>2</Id> <FlightNumber>1121</FlightNumber> </Segment> </Segments> </Flight> <Flight> <Segments> <Segment> <Id>3</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>4</Id> <FlightNumber>2584</FlightNumber> </Segment> </Segments> </Flight> <Flight> <Segments> <Segment> <Id>5</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>6</Id> <FlightNumber>2584</FlightNumber> </Segment> <Segment> <Id>7</Id> <FlightNumber>2023</FlightNumber> </Segment> </Segments> </Flight> </Flights> </Result> </Response> 

the desired, correct result is output:

 <FilterResult> <ResultCount>1</ResultCount> <Response> <Flight> <Segments> <Segment> <Id>3</Id> <FlightNumber>2121</FlightNumber> </Segment> <Segment> <Id>4</Id> <FlightNumber>2584</FlightNumber> </Segment> </Segments> </Flight> </Response> </FilterResult> 

Explanation

The correct use of the law of double negation .

+2
source
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*" /> <xsl:variable name="requested" select="/Response/Request/RequestedFlights/FlightId/text()" /> <xsl:template name="flights-as-string"> <xsl:param name="Id" /> <xsl:for-each select="$Id"> <xsl:sort select="." /> <xsl:value-of select="concat('[',.,']')" /> </xsl:for-each> </xsl:template> <xsl:variable name="requested-str-nodeset"> <xsl:call-template name="flights-as-string"> <xsl:with-param name="Id" select="$requested" /> </xsl:call-template> </xsl:variable> <xsl:variable name="requested-str" select="exsl:node-set($requested-str-nodeset)/text()" /> <xsl:template match="/*"> <xsl:variable name="flight-output"> <xsl:apply-templates select="Result/Flights/Flight" /> </xsl:variable> <FilterResult> <ResultCount><xsl:value-of select=" count( exsl:node-set($flight-output)/Flight)" /></ResultCount> <Response> <xsl:copy-of select="$flight-output" /> </Response> </FilterResult> </xsl:template> <xsl:template match="Flight"> <xsl:variable name="actual-str"> <xsl:call-template name="flights-as-string"> <xsl:with-param name="Id" select="Segments/Segment/FlightNumber/text()" /> </xsl:call-template> </xsl:variable> <xsl:if test="$requested-str = exsl:node-set($actual-str)/text()"> <xsl:copy-of select="." /> </xsl:if> </xsl:template> </xsl:stylesheet> 
+1
source

Source: https://habr.com/ru/post/1447449/


All Articles