Search code examples
xmlxslt

XSLT - match when value exists in list or array


I have several giant books and I want to pull out specific items based on a list of ID values. Is the value in the array? If so, copy, if not ignore.

Seems so basic there should be an answer somewhere, but every post seems far more convoluted. I've tried this various different ways and I can't seem to get it to work: parameter, variable, using exsl:node-set (which I'm unfamiliar with apart from SO answers to similar yet more complicated questions).

Input XML

<?xml version="1.0" encoding="UTF-8"?>
<sec xmlns:xlink="http://www.w3.org/1999/xlink">
   <title>Section Title</title>
   <fig id="img01">
      <caption><title>Image 1</title></caption>
      <graphic xlink:href="img01.eps"/>
   </fig>

   <fig id="img02">
      <caption><title>Image 2</title></caption>
      <graphic xlink:href="img02.eps"/>
   </fig>
</sec>

Input list of images img02, img12, img23, img34, etc...

Desired Output XML

<?xml version="1.0" encoding="UTF-8"?>
<sec xmlns:xlink="http://www.w3.org/1999/xlink">
   <title>Section Title</title>
   <fig id="img02">
      <caption><title>Image 2</title></caption>
      <graphic xlink:href="img02.eps"/>
   </fig>
</sec>

XSLT Sample

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:xlink="http://www.w3.org/1999/xlink" exclude-result-prefixes="exsl" version="2">

    <xsl:param name="ListOfImages" as="element()">
        <item>img02</item>
        <item>hundreds-of-image-IDs</item>
    </xsl:param>

    <xsl:template match="/">
        <sec>
            <xsl:apply-templates/>
        </sec>

    </xsl:template>

    <xsl:template match="fig[exsl:node-set($ListOfImages)/item = exsl:node-set(@id)]">
        <p>Image Name: <xsl:value-of select="@id"/></p>
        <xsl:copy-of select="."/>
    </xsl:template>

    <xsl:template match="@* | node()">
        <xsl:apply-templates/>
    </xsl:template>

</xsl:stylesheet>

Solution

  • I would use a list of ids as a parameter e.g.

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="#all"
        version="3.0">
      
      <xsl:param name="id-list" as="xs:string*" select="'img02', 'img12', 'img23'"/>
    
      <xsl:mode on-no-match="shallow-copy"/>
    
      <xsl:template match="fig[not(@id = $id-list)]"/>
      
    </xsl:stylesheet>
    

    Saxon 9.8 supports XSLT 3.