Re: [xsl] Identifying unique attribute values in nested sibling elements

Subject: Re: [xsl] Identifying unique attribute values in nested sibling elements
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 29 Sep 2011 17:12:52 -0400
At 2011-09-29 13:49 -0700, Mark wrote:
(1) Please think of the <Value> attributes as though 'kc-value' were equivalent to 'dollars' and 'h-value' to 'cents' (the l-value mentioned earlier is like those US stamps issued just before a rate change that are expressed as a letter value). <Value> attributes can only appear [ignoring the specific instance values given here] in the following combination:

<Value kc-value="1"> think of this as $1.
<Value kc-value="1" h-value="50"> Think of this as $1.50
<Value kc-value="0" h-value="50"> Think of this as $0.50
<Value kc-value="0" l-value="A" Think of this as one of those strange rate-change postage stamps that have a letter value of 'A'.


Note that kc-value is required, the other two, h-value and l-value, are both optional and are mutually exclusive. When l-value is present, kc-value must be set to the value '0'.

I'll assume you already have pre-validation for that.


(2) These <Value> elements would produce this XHTML for the particular target XHTML page:

<a href="../aval/1.htm">1kc</a>
<a href="../aval/1-50.htm">1.50kc</a>
<a href="../aval/0-50.htm">40h</a> <!-- think of 40cents -->
<a href="../aval/a.htm">A</a>
...
This is why I was ineptly trying to change my strings back into nodes.

Please don't use words like "ineptly" ... many on this list are also trying to learn these principles. You just had a perspective that wasn't taking advantage of the inherent XML facilities in XSLT. XSLT was designed *for* XML, not just a tack-on of a bunch of subroutines as is true for non-XML languages.


(3) I need to modify your 'reports' function to accommodate all four possibilities, but do not know enough about XPath to do it. May I bother you one more time to show me how?

This is untested, but it is a simple walk through the iterations ... note in XSLT the <xsl:choose> is not a switch (requiring unique cases), rather it is an "if-elseif-elseif-elseif-else" construct, so the first one that is true wins:


  <!--common reporting-->
  <xsl:variable name="dir">../aval/</xsl:variable>
  <xsl:function name="m:report">
    <xsl:param name="Stamp"/>
    <xsl:for-each select="$Stamp/Value">
      <xsl:choose>
        <xsl:when test="@l-value">
          <!--ignore kc-value and h-value-->
          <a href="{$dir}{lower-case(@l-value)}.htm">
            <xsl:value-of select="@l-value"/>
          </a>
        </xsl:when>
        <xsl:when test="@kc-value='0'">
          <!--ignore kc-value-->
          <a href="{$dir}0-{@h-value}.htm">
            <xsl:value-of select="@h-value"/>h<xsl:text/>
          </a>
        </xsl:when>
        <xsl:when test="@h-value">
          <!--both in play-->
          <a href="{$dir}{@kc-value}-{@h-value}.htm">
            <xsl:value-of select="@kc-value"/>.<xsl:text/>
            <xsl:value-of select="@h-value"/>kc<xsl:text/>
          </a>
        </xsl:when>
        <xsl:otherwise>
          <a href="{$dir}{@kc-value}.htm">
            <xsl:value-of select="@kc-value"/>kc<xsl:text/>
          </a>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:function>


As an aside, the stylesheet transforms the XML into an XHTML page for every <Stamp> element, and to an additional page for each of the different <Formats> elements (there are five optional possibilities).

Remember that in XSLT 2 you can nest <xsl:result-document> constructs, so that while you are building your <Stamp> result, you can detour and write out a complete <Formats> result and then get back to where you were building your <Stamp> result. You don't have to finish the outer one to write the inner one, but you do have to finish the inner one before continuing the outer one.


It is *extremely* easy for me to identify which pages to generate when I am in the context of a <Stamp> element that has certain characteristics (and these characteristics change). I suspect that someone with your sophistication could do it from the context of the <Set> element, but it escapes me how to do it that way. This is why I keep rewriting the suggestions I have received to operate from within the context of a <Stamp> element rather than from within the context of the enclosing <Set> element. Dumb, I know, but I already know how to do it.

Again, please don't use the word "dumb". Without knowing your requirements intimately I think your intuition is sound: you say you need to act on the (I'm assuming unique) <Stamp> element, so act on it in my report function. If you need to act on *every* <Formats> in then do it outside of the handling of <Stamp>. If you only act on the ones in <Stamp>, then do so when handling <Stamp>. You won't be interrupting your <Stamp> output if you completely write a <Formats> result.


I have overrun my daily (weekly!) contribution time for vounteering so will leave it in what I'm sure are your capable hands if you pause to look at the big picture of what you are trying to do.

Good luck!

. . . . . . . . . . . Ken



--
Contact us for world-wide XML consulting and instructor-led training
Crane Softwrights Ltd.            http://www.CraneSoftwrights.com/s/
G. Ken Holman                   mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Google+ profile: https://plus.google.com/116832879756988317389/about
Legal business disclaimers:    http://www.CraneSoftwrights.com/legal

Current Thread