Search code examples
xslt-2.0

xpath expression to select specific xml nodes that are available in a file


I was trying to find the out a way for my strange problem.

How to write an xpath to select specific xml nodes that are available in another text file.

For Instance,

<xsl:for-each select="SUBSCRIBER_PROFILE_LIST/SUBSCRIBER_PROFILE_INFO[GROUP_NAME eq  (group name list in a text file as input)]">

For example,

<xsl:for-each select="SUBSCRIBER_PROFILE_LIST/SUBSCRIBER_PROFILE_INFO[GROUP_NAME eq collection('select_nodes.txt')]">

select_nodes.txt contains list of string that can be selected only
For example
ABC
IJK


<SUBSCRIBER>
    <MSISDN>123456</MSISDN>
    <SUBSCRIBER_PROFILE_LIST>
        <SUBSCRIBER_PROFILE_INFO>
            <PROFILE_MSISDN>12345</PROFILE_MSISDN>
            <GROUP_NAME>ABC</GROUP_NAME>
            <GROUP_ID>18</GROUP_ID>
        </SUBSCRIBER_PROFILE_INFO>
        <SUBSCRIBER_PROFILE_INFO>
            <PROFILE_MSISDN>456778</PROFILE_MSISDN>
            <GROUP_NAME>DEF</GROUP_NAME>
            <GROUP_ID>100</GROUP_ID>
        </SUBSCRIBER_PROFILE_INFO>
        <SUBSCRIBER_PROFILE_INFO>
            <PROFILE_MSISDN>78876</PROFILE_MSISDN>
            <GROUP_NAME>IJK</GROUP_NAME>
            <GROUP_ID>3</GROUP_ID>
        </SUBSCRIBER_PROFILE_INFO>
</SUBSCRIBER>

Solution

  • XSLT2 has limited functionality for parsing arbitrary text files. I would suggest:

    1. Make the select_nodes.txt an XML file and load it using the doc() function:

      <xsl:variable name="group_names" as="xs:string *"
        select="doc('select_nodes.xml')/groups/group"/>
      

      with select_nodes.xml looking like this:

      <?xml version="1.0" encoding="UTF-8"?>
      <groups>
        <group>ABC</group>
        <group>IJK</group>
      </groups>
      
    2. Pass the group names as a stylesheet parameter. (How you do this depends on which XSLT engine you're using and whether it's through the command line or an API.) If it's through an API, then you may be able to pass the values in directly as xs:string-typed objects. Otherwise you'll have to parse the parameter:

      <xsl:param name="group_names_param"/>
      
      <!-- Assuming the input string is a whitespace-separated list of names -->
      <xsl:variable name="group_names" as="xs:string *"
        select="tokenize($group_names_param, '\s+')"/>
      

    In either case your for-each expression would then look like this:

    <xsl:for-each select="
      SUBSCRIBER_PROFILE_LIST/SUBSCRIBER_PROFILE_INFO[GROUP_NAME = $group_names]">
      <!-- Do something -->
    </xsl:for-each>