Home > OS >  XSLT: access the xml configuration in the XSLT file
XSLT: access the xml configuration in the XSLT file

Time:05-05

I am trying to print the fruit names which is not in the data:fruit. In my case I expect Pineapple, Kiwi. I am accessing the data:fruit in the XSLT xml configuration by 'select="document('')/*/data:fruit/attribute/@value"'. Currently I am getting the following error.

Error:

Error executing XSLT at line 24 : Exception thrown by URIResolver resolving `` against `'. Found while atomizing the first argument of fn:string-join()

Please check the following xsltfiddle link: https://xsltfiddle.liberty-development.net/jyfAiC7/4

xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:exsl="http://exslt.org/common" 
                xmlns:set="http://exslt.org/sets" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                extension-element-prefixes="exsl" 
                version="2.0">

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    <data:fruit>        
        <attribute  value="Pineapple" />
        <attribute  value="Kiwi" />
        <attribute  value="Apple" />
        <attribute  value="Orange" />
        <attribute  value="Banana" />
        <attribute  value="Cherry" />
        <attribute  value="Peach" />
    </data:fruit>           
                
    <xsl:template match="/">

            <xsl:variable name="fruitMissing"> 
                <xsl:for-each select="document('')/*/data:fruit/attribute/@value">
                    <xsl:variable name="fruit" select="."/>
                    <xsl:if test="count(//root/details/item/line[contains(.,$fruit)])=0"><xsl:value-of select="."/>,</xsl:if>
                </xsl:for-each>
            </xsl:variable>
            
            <xsl:value-of select="$fruitMissing"/> 
    </xsl:template>
</xsl:stylesheet>

xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
     <header/>
     <details>
          <item>
               <line>14.04.22 5:04:30;Apple;Finished</line>
          </item>
              <item>
               <line>14.04.22 3:36:42;Apple;Finished</line>
          </item>
          <item>
               <line>14.04.22 4:03:47;Orange;Finished</line>
          </item>
            <item>
               <line>14.04.22 2:40:33;Orange;Finished</line>
          </item> 
          <item>
               <line>14.04.22 3:37:12;Banana;Finished</line>
          </item>
          <item>
               <line>14.04.22 3:36:59;Cherry;Finished</line>
          </item>
          <item>
               <line>14.04.22 3:36:57;Peach;Finished</line>
          </item>
     </details>
     <summary/>
     <statistics/>
     <exceptions/>
</root>

CodePudding user response:

I would suggest you do it this way:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:key name="existing-fruit" match="item" use="tokenize(line, ';')[2]" />

<xsl:variable name="fruit">
    <attribute value="Pineapple" />
    <attribute value="Kiwi" />
    <attribute value="Apple" />
    <attribute value="Orange" />
    <attribute value="Banana" />
    <attribute value="Cherry" />
    <attribute value="Peach" />
</xsl:variable>

<xsl:template match="/" >
    <xsl:variable name="xml" select="." />
    <xsl:value-of select="$fruit/attribute[not(key('existing-fruit', @value, $xml))]/@value" separator=","/>
</xsl:template>

</xsl:stylesheet>

Beside being shorter and more efficient, it also avoids possible false positive match on other values included in line.


Demo: https://xsltfiddle.liberty-development.net/jyfAiC7/5

CodePudding user response:

Try this XSLT2:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
            xmlns:exsl="http://exslt.org/common" 
            xmlns:set="http://exslt.org/sets" 
            xmlns:data="http://mulocal/host" 
            xmlns:xs="http://www.w3.org/2001/XMLSchema" 
            extension-element-prefixes="exsl" 
            version="2.0">

<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<data:fruit>        
    <attribute  value="Pineapple" />
    <attribute  value="Kiwi" />
    <attribute  value="Apple" />
    <attribute  value="Orange" />
    <attribute  value="Banana" />
    <attribute  value="Cherry" />
    <attribute  value="Peach" />
</data:fruit>           
            
<xsl:template match="/">
    <xsl:variable name="varInput" select="root"/>
        <xsl:for-each select="document('')/*/data:fruit/attribute/@value">
            <xsl:variable name="fruit" select="."/>
              <xsl:if test="count($varInput/details/item/line[contains(.,$fruit)])=0">
                <xsl:value-of select="."/><xsl:text>,</xsl:text>
            </xsl:if>
         </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Result:

<?xml version="1.0" encoding="UTF-8"?>Pineapple,Kiwi,
  • Related