xpath - XSLT 使用 XSLT 数组过滤结果

标签 xpath xslt-1.0 transformation xslt

我是 XSLT 的初学者。

下面是我收到的源 XML。 Request标签包含 FlightId用于过滤 Result标签。

源 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>

说明 :

正确使用 double negation 法律。

关于xpath - XSLT 使用 XSLT 数组过滤结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13491404/

相关文章:

r - dplyr transmute 返回比原始数据帧更少的行

arrays - 是否有一种算法可以找到将数组转换为新状态所需的最小转换集

php - 使用 PHP 查找所有 XML 命名空间 URI

c# - 开源C#XPath 2.0过滤器

xslt - XSLT 1.0中的"Regular expression"-style替换

xml - XML 和 XSL 中的前缀命名空间处理通过 XML 解析器返回错误

jQuery css 多个 Transform 属性不起作用

python - 使用 lxml 从 xml 文件获取值

c# - 用于查找最近的前一个兄弟的 XPath 语句

XSLT 身份转换而不更改输出