Eclipse Xquery For Complex payload

2019-08-28 04:11发布

问题:

I have the input request like below

 <Input>
    <BusinessObjects>
          <BusinessObject>
            <BusinessIdentifiers>
              <BusinessIdentifier>
                <BKey>BuCode</BKey>
                <BValue>CDC</BValue>
              </BusinessIdentifier>
              <BusinessIdentifier>
                <BKey>BuType</BKey>
                <BValue>123</BValue>
              </BusinessIdentifier>
              <BusinessIdentifier>
                <BKey>CsmNo</BKey>
                <BValue>857895</BValue>
              </BusinessIdentifier>
            </BusinessIdentifiers>
           </BusinessObject>
          <BusinessObject>
            <BusinessIdentifiers>
              <BusinessIdentifier>
                <BKey>BuCode</BKey>
                <BValue>CDC</BValue>
              </BusinessIdentifier>
              <BusinessIdentifier>
                <BKey>BuType</BKey>
                <BValue>123</BValue>
              </BusinessIdentifier>
              <BusinessIdentifier>
                <BKey>CsmNo</BKey>
                <BValue>34567</BValue>
              </BusinessIdentifier>
            </BusinessIdentifiers>
            </BusinessObject>      
        </BusinessObjects>
        </Input>

i need to form an output like below schema

<Output>
<BusinessObject>
<BIKey></BIKey>
<BKey></BIKey>
<Bvalue></Bvalue>
<BOID></BOID>
</BusinessObject>
</Output>

For the above payload The output should be

  <Output>
    <BusinessObjects>
    <BusinessObject>
    <BIKey>CDC:123:857895|CDC:123:34567</BIKey>
    <BKey>BUCode</BKey>
    <Bvalue>CDC</Bvalue>
    <BOID>CDC:123:857895</BOID>
    </BusinessObject>
    <BusinessObject>
    <BIKey>CDC:123:857895|CDC:123:34567</BIKey>
    <BKey>BUtype</BKey>
    <Bvalue>123</Bvalue>
    <BOID>CDC:123:857895</BOID>
    </BusinessObject>
    <BusinessObject>
    <BIKey>CDC:123:857895|CDC:123:34567</BIKey>
    <BKey>CSMNo</BKey>
    <Bvalue>857895</Bvalue>
    <BOID>CDC:123:857895</BOID>
    </BusinessObject>
    <BusinessObject>
    <BIKey>CDC:123:857895|CDC:123:34567</BIKey>
    <BKey>BUCode</BKey>
    <Bvalue>CDC</Bvalue>
    <BOID>CDC:123:34567</BOID>
    </BusinessObject>
    <BusinessObject>
    <BIKey>CDC:123:857895|CDC:123:34567</BIKey>
    <BKey>BUtype</BKey>
    <Bvalue>123</Bvalue>
    <BOID>CDC:123:34567</BOID>
    </BusinessObject>
    <BusinessObject>
    <BIKey>CDC:123:857895|CDC:123:34567</BIKey>
    <BKey>CSMNo</BKey>
    <Bvalue>857895</Bvalue>
    <BOID>CDC:123:34567</BOID>
    </BusinessObject>
    </BusinessObjects>
    </Output>

i have tried below Xquery to get the same but ended up with errors or not meeting the requiremnt

<Ouput>
<BusinessObjects>
{
for $bi in Input/BusinessObjects/BusinessObject/BusinessIdentifiers/BusinessIdentifier
return
<BIKey>
    {
        string-join(
            for $bo in Input/BusinessObjects/BusinessObject return string-join($bo/BusinessIdentifiers/BusinessIdentifier/BValue, '|'),
            ':'
        )
    }
    </BIKey>
    <BKey>data {$bi/Bkey}</BKey>
    <Bvalue>data {$bi/Bvalue}</Bvalue>
    for $bo in Input/BusinessObjects/BusinessObject return <BOID>{string-join($bo//BValue, ':')}<BOID>

}
</BusinessObjects>
</Ouput>

the description for the output fields as follows BIKey-->it has formed with all the Bvalues of 'Business Identifier' concatenated with ':' and then for each businessobject it is separed with '|' Bkey-->Straight mapping with bkey Bvalue-->Straight mapping with Bvalue BOID--> it has to formed for each businessobject, need to concatenate the values Bvalues of Business Identifiers with ':' Any suggestions, i believe that i have to two complex loops in here, but not able to crack it.

Thanks for @Martin as he helped me to crack this using 'ancestor' axis, but some how eclispe is not identifying 'ancestor'.

Thanks

回答1:

The BIKey will be the same for all of the output, so we can compute it outside of any loop and be done with it. We do so by joining all the BValues of a BusinessObject with :, and joining the result of this for each BusinessObject with | :

let $BIKey := string-join(for $bo in /Input/BusinessObjects/BusinessObject return string-join($bo/BusinessIdentifiers/BusinessIdentifier/BValue, ':'), '|')

The BOID will depend on the BusinessObject we're handling, so we need to loop over those and we can extract the BOID at that point :

let $BIKEY := [...]
for $bo in /Input/BusinessObjects/BusinessObject
  let $BOID := string-join($bo/BusinessIdentifiers/BusinessIdentifier/BValue, ':')

The rest of the output fields depend on the BusinessIdentifier, so let's loop on these too and return a BusinessObject per BusinessIdentifier :

let $BIKEY := [...]
for $bo in [...]
  let $BOID :=  [...]
  return for $bi in $bo/BusinessIdentifiers/BusinessIdentifier/
    return <BusinessObject>
             <BIKey>{$BIKEY}</BIKey>
             <BKey>{$bi/BKey}</BKey>
             <Bvalue>{$bi/Value}</Bvalue>
             <BOID>{$BOID}</BOID>
           </BusinessObject>

Now all we need is to wrap those output BusinessObjects into their parent tags :

<output><BusinessObjects>{
let $BIKEY := string-join(for $bo in /Input/BusinessObjects/BusinessObject return string-join($bo/BusinessIdentifiers/BusinessIdentifier/BValue, ':'), '|')
for $bo in /Input/BusinessObjects/BusinessObject
  let $BOID := string-join($bo/BusinessIdentifiers/BusinessIdentifier/BValue, ':')
  return
    for $bi in $bo/BusinessIdentifiers/BusinessIdentifier
    return <BusinessObject>
<BIKey>{$BIKEY}</BIKey>
<BKey>{$bi/BKey/text()}</BKey>
<Bvalue>{$bi/BValue/text()}</Bvalue>
<BOID>{$BOID}</BOID>
</BusinessObject>
}</BusinessObjects></output>

You can test it here.