2012-11-21 29 views
4

我是XSLT的初學者。使用XSLT數組的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> 

請幫助我。我應該如何使用數組來過濾響應並獲得預期的輸出。 謝謝。

+0

很好地構建的問題。 +1。 –

+0

當有兩個FlightNumbers時,爲什麼是ResultCount 1? –

+0

@ SeanB.Durkin ResultCount 1,因爲「FilterFlights」變量應該只有一個'Flight'節點。 –

回答

2

使用

/*/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> 

說明

正確使用double negation法。

+0

謝謝。對於給定的源XML,您的解決方案起作用。但是當我需要對不同的結構化XML應用相同的法則時。我應該創建新的問題還是編輯它? –

+0

@AnkurRaiyani,如果你創建一個新的問題對每個人都好 - 否則你會破壞第一個問題,或者使其不易讀。 –

+0

謝謝。讓我這樣做。 –

1
<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> 
+0

感謝您的辛勤工作! –