XSLT only adds node attribute if source attribute exists

I want to add an attribute element to node if and only if there is a data source for this attribute.

In other words, I do not want to end with empty attributes if the source does not match my rule.

<tok id="t1" fooID=""/> //not accepted
<tok id="t1" /> //instead of ^
<tok id="t1" fooID="bar"/> //accepted


Moreover, I would like to check if the source has more than 1 node that matches my current attribute, and if so, add another attribute foowith "source2". Here is what I am using now:
<xsl:template match="tokens/token">
<tok id="{@ID}" 
     ctag="{/root/myStuff/fooSources[1and2 how?]/fooSource[@fooID=current()/@ID]}" 
>
</tok>

The source XML looks like this:

<root>
   <myStuff>
      <tokens>
         <token ID="bar"/>
         <token ID="anotherBar"/>
         <token ID="noFoo"/>
      </tokens>

      <fooSources>
         <fooSource fooID="bar"> kitten </fooSource>
         <fooSource fooID="anotherBar"> shovel </fooSource>
      </fooSources>

      <fooSources>
         <fooSource fooID="bar"> kitty </fooSource>
         <fooSource fooID="notAnotherBar"> fridge </fooSource>
      </fooSources>
   </myStuff>
</root>

The desired result will be as follows:

<tok id="bar" fooID="kitten" fooID_2="kitty"/>
<tok id="anotherBar" fooID="shovel"/> 
<tok id="noFoo" /> 

Thanks in advance for your help!

PS: I would like to do this in xpath 1.0

+3
source share
2 answers

PS: I would like to do this in xpath 1.0

XPath - XML, .

( ), , XPath. , XML, - XSLT.

XSLT 1.0:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kFooIdByVal" match="fooSource/@fooID"
  use="."/>

 <xsl:template match="token">
  <tok>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates
        select="key('kFooIdByVal',@ID)"/>
  </tok>
 </xsl:template>

 <xsl:template match="@fooID">
  <xsl:variable name="vattrName"
   select="concat('fooID',
                  substring(concat('_',position()),
                            1 div (position() >1)
                           )
                  )
   "/>

  <xsl:attribute name="{$vattrName}">
   <xsl:value-of select="normalize-space(..)"/>
  </xsl:attribute>
 </xsl:template>
 <xsl:template match="fooSources"/>
</xsl:stylesheet>

XML-:

<root>
    <myStuff>
        <tokens>
            <token ID="bar"/>
            <token ID="anotherBar"/>
            <token ID="noFoo"/>
        </tokens>
        <fooSources>
            <fooSource fooID="bar"> kitten </fooSource>
            <fooSource fooID="anotherBar"> shovel </fooSource>
        </fooSources>
        <fooSources>
            <fooSource fooID="bar"> kitty </fooSource>
            <fooSource fooID="notAnotherBar"> fridge </fooSource>
        </fooSources>
    </myStuff>
</root>

, :

<tok ID="bar" fooID="kitten" fooID_2="kitty"/>
<tok ID="anotherBar" fooID="shovel"/>
<tok ID="noFoo"/>

  • , token, tok element that has all the existing attributes (if any) of the matched token element. It also applies templates on any fooID attribute, whose value is the same as the value of the ID attribute of the current (matched) node. If there isn't any such fooID`, .

  • , fooID, "fooID_{N}", N - node ( fooID) node -list ( <xsl:apply-templates>, fooID). N 1, ("fooID") "_"{N}.

  • XSLT, , fooSources, () .

+3
<foo>
   <xsl:if test="@bar">
      <xsl:attribute name="id">
         <xsl:value-of select="@bar"/>
      </xsl:attribute>
   </xsl:if>
</foo>
+5

All Articles