Search code examples
xmlxslt-1.0xqueryibm-datapower

Filtering one XML using nodes from a second XML in XSLT 1.0


Below are two XML files. I want to filter XMLA to only those people who exist in XMLB, using the name field.

Both the XML documents are stored in the variables $XMLA and $XMLB.

I created the output using XQuery 1.0 but I am not sure how to perform the same operation in XSLT 1.0.

XMLA:

<table>
 <row>
  <name>NNN</name>
  <address>1234 NN</address>
  <phone>23423423</phone>
 </row>
 <row>
  <name>kkk</name>
  <address>1234 KK</address>
  <phone>4343434</phone>
  </row>
</table>

XMLB:

<table>
 <row>
  <id>1111</id>
  <batch>1212</batch>
  <name>NNN</name>
 </row>
 <row>
  <id>2222</id>
  <batch>2121</batch>
  <name>kkk</name>
 </row>
</table>

XQuery:

for $y in fn:doc('XMLA.xml')/table/row
for $x in fn:doc('XMLB.xml')/table/row
for $a in $x/name
where $y/name = $a
order by $y/name
return $y

The reason I am looking into XSLT is because the parsing on large XML file is extremely slow with XQuery. I am not sure if that is because of my XQuery built wrong, but I want to give XSLT a try and compare the efficiency.


Solution

  • It looks like your XQuery approach allocates a brand-new document B for every <row> in document A.

    Use variables to store the documents once.

    xquery version "1.0";
    
    (: your call to fn:doc('XMLA.xml') here :)
    let $A := <table>
     <row>
      <name>NNN</name>
     </row>
     <row>
      <name>kkk</name>
     </row>
     <row>
      <name>xxx</name>
     </row>
    </table>
    
    (: your call to fn:doc('XMLB.xml') here :)
    let $B := <table>
     <row>
      <name>nnnn</name>
     </row>
     <row>
      <name>kkk</name>
     </row>
     <row>
      <name>xxx</name>
     </row>
    </table>
    
    let $nameA := $A/row/name
    let $nameB := $B/row/name
    
    for $name in $nameA
    where $name = $nameB
    order by $name
    return $name
    

    returns

    <name>kkk</name>
    <name>xxx</name>
    

    for me. Check if performance improves.