我是XSLT的初学者。
下面是我收到的源XML。Request
标签固定用于过滤Result
标签的FlightId
。
源XML:
<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>
我使用上面的XSLT收到了下面的输出。
输出:
<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>
我希望收到以下输出。
预期输出:
<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>
请帮帮我。我应该如何使用数组来过滤响应并获得预期的输出。谢谢
使用:
/*/Result/*/Flight
[count(*/*)=count(/*/Request/*/FlightId)
and
not(*/*/FlightNumber[not(. = /*/Request/*/FlightId)])
]
这是完整的转换:
<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>
当此转换应用于所提供的XML文档时:
<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>
生成所需的正确结果:
<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>
解释:
正确使用双重否定定律。
<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>