jjasper0729
jjasper0729

Reputation: 295

xslt 1.0 - Trying to get nodes for a specific value

I've got an XML file that has many similarly named nodes but attributes within certain nodes are unique. I want to output into an HTML page only the nodes that fall under a certain attribute value.

Here is the xml:

<document>
  <component>
    <section>
      <templateId value="temp_1" />
      <entry>
        <act>
          <code displayName="temp_1:code_1" />
        </act>
      </entry>
      <entry>
        <act>
          <code displayName="temp_1:code_2" />
        </act>
      </entry>
      <entry>
        <act>
          <code displayName="temp_1:code_3" />
        </act>
      </entry>
    </section>
    <section>
      <templateId value="temp_2" />
      <entry>
        <act>
          <code displayName="temp_2:code_1" />
        </act>
      </entry>
      <entry>
        <act>
          <code displayName="temp_2:code_2" />
        </act>
      </entry>
    </section>
  </component>
</document>

From this specific example, I want to only get the displayName value from the section that has the templateId value of temp_2. This is the XSL code that I'm using but it is getting everything, not just the section that I want. i know the first "when" is working because the right header (between the span tags) is displaying properly. It's just the for-each through the entries.

<xsl:tempalte match="/">
<xsl:choose>
  <xsl:when test="//templateId/@value='temp_2'">
    <div style="margin-bottom: 5px; padding: 5px; border-bottom: 1px solid #000000;">
      <span style="font-weight: bold;">Template 2: </span>
      <br />
      <xsl:choose>
        <xsl:when test="count(//section/entry) != 0">
          <xsl:for-each select="//section/entry">
            <xsl:choose>
              <xsl:when test="position() = 1">
                <xsl:value-of select="act/code/@displayName" />
              </xsl:when>
              <xsl:otherwise>
                <br/>
                <xsl:value-of select="act/code/@displayName" />
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
          No codes to display
        </xsl:otherwise>
      </xsl:choose>
    </div>
  </xsl:when>
</xsl:choose>
</xsl:template>

It should display like so:

temp_2:code_1
<br>temp_2:code_2

Any help would be greatly appreciated.

Upvotes: 0

Views: 1448

Answers (2)

user663031
user663031

Reputation:

I guess you want to completely restudy XSLT and its philosophy. Don't program it like it was BASIC. The basic pattern, at least for your case, is that an XSLT program is a collection of templates to handle matching elements. Instead of littering your code with if and choose, write templates with the proper matching conditions. Instead of BASIC's FOR I=1 TO 10, use <xsl:apply-templates/> to "iterate" over the children. Here's the basic idea:

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

<xsl:template match="templateId"/> <!-- skip templateID elements by default -->

<xsl:template match="templateId[@value='temp_2']">
    <div style="margin-bottom: 5px; padding: 5px; border-bottom: 1px solid #000000;">          
        <span style="font-weight: bold;">Template 2: </span>
        <xsl:apply-templates/>
    </div>
</xsl:template>

<xsl:template match="code">
    <xsl:value-of select="@displayName"/>
    <xsl:if test="position() != 1"><br/></xsl:if>
</xsl:template>

<xsl:template match="section[count(entry)=0]">
    No codes to display
</xsl:template>

Why no template for act elements? Well, by default XSLT will provide you with a template which does a <xsl:apply-templates/>.

Upvotes: 1

Matthew Green
Matthew Green

Reputation: 10401

Based on your description it sounds like you only want the temp_2 values in your for-each.

That being the case you can just update your select to the following:

<xsl:for-each select="//section[templateId/@value = 'temp_2']/entry">

This says to grab any entry under section that has a templateId with an attribute of value that equals 'temp_2'.

Upvotes: 0

Related Questions