Xquery поможет отсортировать родительские и дочерние отношения - PullRequest
0 голосов
/ 14 мая 2011

У меня есть приведенный ниже xml (упрощенный и анонимный из реального ввода), он в основном содержит список политик, которые имеют дату начала политики, ссылку на политику и ссылку на родительскую политику (где 0 указывает отсутствие родителя)

То, что я пытаюсь достичь, - это вывод формы.

  • Самая старая политика сверху (самая старая Дата начала)
    • Если у него есть дети, его дети должны следовать (также упорядочено по самой старшей дате начала)
  • Вслед за следующей самой старой недетской политикой
    • Если у него есть дети, его дети должны следовать (также упорядочены по самой старшей дате начала)
  • и повтор

Это на самом деле поставило меня в тупик, я пробовал разные вещи, но вот моя последняя попытка.

{
let $rows:= for $x in SOAP-ENV:Envelope/SOAP-ENV:Body/cus:GetCustPolicyResponse/cus:Policy/cus:PolicyRow
order by $x/cus:DateStart
return $x
for$policy in distinct-values($rows/cus:PolRef)
for $parentPolicy in distinct-values($rows/cus:parentPolRef)
        for $row in $rows
        where $row/cus:parentPolRef =$parentPolicy  and $row/cus:PolRef =$policy
        return <tr>
                <td>{$row/cus:PolRef/text()}</td>
                <td>{$row/cus:parentPolRef/text()}</td>
                <td>{$row/cus:DateStart/text()}</td>
                </tr>
}

XML

<SOAP-ENV:Envelope xmlns:SOAP-ENV="hp://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="hp://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="hp://www.w3.org/2001/XMLSchema">
   <SOAP-ENV:Body>
      <GetCustPolicyResponse xmlns="hp://www.client.com/services/customer">
         <Policy>
            <PolicyRow>
               <PolRef>1</PolRef>
               <DateStart>2011-04-01</DateStart>
               <parentPolRef>0</parentPolRef>
            </PolicyRow>
            <PolicyRow>
               <PolRef>2</PolRef>
               <DateStart>2011-04-01</DateStart>
               <parentPolRef>0</parentPolRef>
            </PolicyRow>
            <PolicyRow>
               <PolRef>3</PolRef>
               <DateStart>2011-04-20</DateStart>
               <parentPolRef>0</parentPolRef>
            </PolicyRow>
            <PolicyRow>
               <PolRef>20</PolRef>
               <DateStart>2011-04-02</DateStart>
               <parentPolRef>1</parentPolRef>
            </PolicyRow>
             <PolicyRow>
               <PolRef>21</PolRef>
               <DateStart>2011-04-01</DateStart>
               <parentPolRef>1</parentPolRef>
            </PolicyRow>
            <PolicyRow>
               <PolRef>26</PolRef>
               <DateStart>2011-04-22</DateStart>
               <parentPolRef>3</parentPolRef>
            </PolicyRow>
            <PolicyRow>
               <PolRef>4</PolRef>
               <DateStart>2011-04-03</DateStart>
               <parentPolRef>0</parentPolRef>
            </PolicyRow>
        <PolicyRow>
               <PolRef>25</PolRef>
               <DateStart>2011-04-21</DateStart>
               <parentPolRef>3</parentPolRef>
            </PolicyRow>
            <PolicyRow>
               <PolRef>24</PolRef>
               <DateStart>2011-04-16</DateStart>
               <parentPolRef>2</parentPolRef>
            </PolicyRow>
             <PolicyRow>
               <PolRef>23</PolRef>
               <DateStart>2011-04-17</DateStart>
               <parentPolRef>2</parentPolRef>
            </PolicyRow>
         </Policy>
      </GetCustPolicyResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Требуемый выход

<table>
<tr>
    <td>Policy Reference</td>
    <td>Policy start date</td>
</tr>
<tr>
    <td>1</td>
    <td>2011-04-01</td>
</tr>
<tr>
    <td>21</td>
    <td>2011-04-21</td>
</tr>
<tr>
    <td>20</td>
    <td>2011-04-02</td>
</tr>
<tr>
    <td>2</td>
    <td>2011-04-01</td>
</tr>
<tr>
    <td>24</td>
    <td>2011-04-16</td>
</tr>
<tr>
    <td>23</td>
    <td>2011-04-17</td>
</tr>
<tr>
    <td>4</td>
    <td>2011-04-03</td>
</tr>
<tr>
    <td>3</td>
    <td>2011-04-20</td>
</tr>
<tr>
    <td>25/td>
    <td>2011-04-21</td>
</tr>
<tr>
    <td>26</td>
    <td>2011-04-22</td>
</tr>

Ответы [ 2 ]

1 голос
/ 15 мая 2011

I. Этот код XQuery :

declare namespace  x = "hp://www.client.com/services/customer";  
declare function x:PolicyByParentRef($pNodes as element()*, 
                                     $pRef as xs:string) as element()*
{
  $pNodes[x:parentPolRef eq $pRef]
};

declare function x:ProcessPolicy($pNodes as element()*, 
                                 $pPol as element()) as element()*
{
 if(not(empty($pPol)))
   then  
    (<tr>
        <td>{$pPol/x:PolRef/text()}</td>,
        <td>{$pPol/x:DateStart/text()}</td>
      </tr>,
     for $child-policy in x:PolicyByParentRef($pNodes, $pPol/x:PolRef)
       order by $child-policy/x:DateStart descending
       return
            x:ProcessPolicy($pNodes, $child-policy)
    )
  else ()
};
<table>
{for $topPolicy in  x:PolicyByParentRef(/*/*/*/*/x:PolicyRow,  '0')
    order by $topPolicy/x:DateStart  descending
   return
       x:ProcessPolicy(/*/*/*/*/x:PolicyRow, $topPolicy)
 }
</table>

при применении к предоставленному документу XML :

<SOAP-ENV:Envelope xmlns:SOAP-ENV="hp://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="hp://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="hp://www.w3.org/2001/XMLSchema">
  <SOAP-ENV:Body>
    <GetCustPolicyResponse xmlns="hp://www.client.com/services/customer">
      <Policy>
        <PolicyRow>
          <PolRef>1</PolRef>
          <DateStart>2011-04-01</DateStart>
          <parentPolRef>0</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>2</PolRef>
          <DateStart>2011-04-01</DateStart>
          <parentPolRef>0</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>3</PolRef>
          <DateStart>2011-04-20</DateStart>
          <parentPolRef>0</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>20</PolRef>
          <DateStart>2011-04-02</DateStart>
          <parentPolRef>1</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>21</PolRef>
          <DateStart>2011-04-01</DateStart>
          <parentPolRef>1</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>26</PolRef>
          <DateStart>2011-04-22</DateStart>
          <parentPolRef>3</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>4</PolRef>
          <DateStart>2011-04-03</DateStart>
          <parentPolRef>0</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>25</PolRef>
          <DateStart>2011-04-21</DateStart>
          <parentPolRef>3</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>24</PolRef>
          <DateStart>2011-04-16</DateStart>
          <parentPolRef>2</parentPolRef>
        </PolicyRow>
        <PolicyRow>
          <PolRef>23</PolRef>
          <DateStart>2011-04-17</DateStart>
          <parentPolRef>2</parentPolRef>
        </PolicyRow>
      </Policy>
    </GetCustPolicyResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

дает желаемый результат :

<?xml version="1.0" encoding="UTF-8"?>
<table>
   <tr>
      <td>3</td>,
        <td>2011-04-20</td>
   </tr>
   <tr>
      <td>26</td>,
        <td>2011-04-22</td>
   </tr>
   <tr>
      <td>25</td>,
        <td>2011-04-21</td>
   </tr>
   <tr>
      <td>4</td>,
        <td>2011-04-03</td>
   </tr>
   <tr>
      <td>1</td>,
        <td>2011-04-01</td>
   </tr>
   <tr>
      <td>20</td>,
        <td>2011-04-02</td>
   </tr>
   <tr>
      <td>21</td>,
        <td>2011-04-01</td>
   </tr>
   <tr>
      <td>2</td>,
        <td>2011-04-01</td>
   </tr>
   <tr>
      <td>23</td>,
        <td>2011-04-17</td>
   </tr>
   <tr>
      <td>24</td>,
        <td>2011-04-16</td>
   </tr>
</table>

II. Просто для сравнения - решение XSLT :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:x="hp://www.client.com/services/customer"
 exclude-result-prefixes="x">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kPolicyByRef" match="x:PolicyRow"
  use="x:parentPolRef"/>

 <xsl:template match="/">
  <table>
   <xsl:apply-templates select=
    "key('kPolicyByRef', '0')">
     <xsl:sort select="x:DateStart" order="descending"/>
   </xsl:apply-templates>
  </table>
 </xsl:template>

 <xsl:template match="x:PolicyRow">
  <tr>
    <xsl:apply-templates/>
  </tr>

  <xsl:apply-templates select=
  "key('kPolicyByRef', x:PolRef)">
   <xsl:sort select="x:DateStart" order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="x:PolicyRow/*">
  <td><xsl:value-of select="."/></td>
 </xsl:template>

 <xsl:template match="x:parentPolRef" priority="2"/>
</xsl:stylesheet>
0 голосов
/ 14 мая 2011

Поверьте, у меня наконец есть ответ.

{
let $rows:= for $x in SOAP-ENV:Envelope/SOAP-ENV:Body/cus:GetCustPolicyResponse/cus:Policy/cus:PolicyRow
order by $x/cus:DateStart
return $x

let $parentRows := for $x in SOAP-ENV:Envelope/SOAP-ENV:Body/cus:GetCustPolicyResponse/cus:Policy/cus:PolicyRow
where  $x/cus:parentPolRef = 0
order by $x/cus:DateStart
return $x

for $parentPolicy in $parentRows
    let $children := 
        for $row in $rows
        where$parentPolicy/cus:PolRef = $row/cus:parentPolRef 
        return
        <tr>
        <td style="left-padding 20px;">child {$row/cus:PolRef}</td>
        <td> {$row/cus:DateStart}</td>
        </tr>
return
    <tr>
     <td>parent {$parentPolicy/cus:PolRef }</td>
     <td>{$parentPolicy/cus:DateStart }</td>
    {$children}
    </tr>
}
...