Re: [xsl] global language parameter

Subject: Re: [xsl] global language parameter
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Mon, 15 Feb 2010 00:06:47 -0500
At 2010-02-15 12:06 +0900, Charles Muller wrote:
The way I have been handling paragraphs for years is with this kind of structure:

<xsl:template match="p">
<xsl:choose>
<xsl:when test="@rend='indented'">
<p style="text-indent:12mm; margin-top: 0;
margin-bottom: 0; line-height:9mm;font-family: 'Times Ext Roman', 'Times New Roman'">
<xsl:apply-templates/>
</p>
</xsl:when>
<xsl:when test="@rend='plain'">
<p style="margin-left:0; margin-top:0; margin-bottom:0; text-indent:0mm; line-height:9mm;font-family: 'Times Ext Roman', 'Times New Roman'">
<xsl:apply-templates/>
</p>
</xsl:when>
...
... (etc.)
</xsl:choose>

That is very repetitive and difficult to maintain when you need to make a change.


(all the values remain the same except for the font-family name)

Then perhaps you should try and take a piecemeal approach for maintenance purposes.


I realize that I could create a sub-tree under each attribute name, like

  <xsl:when test="@rend='indented'">
   <xsl:choose>
    <xsl:when test="lang=('en')">
      <p style="text-indent:12mm; margin-top: 0;
      margin-bottom: 0; line-height:9mm;font-family:
      'Times New Roman'">
      <xsl:apply-templates/>
      </p>
    </xsl:when>
    <xsl:when test="lang=('ja')">
      <p style="text-indent:12mm; margin-top: 0;
      margin-bottom: 0; line-height:9mm;font-family:
      Mincho">
      <xsl:apply-templates/>
      </p>
     </xsl:when>

    <xsl:when test="lang=('ko')">
      <p style="text-indent:12mm; margin-top: 0;
      margin-bottom: 0; line-height:9mm;font-family:
      Batang">
      <xsl:apply-templates/>
      </p>
     </xsl:when>
  </xsl:choose>
  </xsl:when>
 <xsl:when test="@rend='plain'">

(etc.)

I could do this, but it certainly seems unwieldy. Or is this the way people usually do it?

I hope not.


Or, is there a more efficient way of making some kind of declaration for xml:lang that would work throughout the document,

"throughout"? So there are many places where you want to change the font family? Then make the common bits you need be reusable so that you can reuse them.


while inserting (concatenating?) the style values *inside* the already existent style values for <p>?

If you need to incrementally build the attribute, then you can do so:


  <xsl:template match="p">
    <p>
      <xsl:attribute name="style">
        <xsl:text>text-indent:12mm; margin-top: 0;</xsl:text>
        <xsl:text>margin-bottom: 0; line-height:9mm;</xsl:text>
        <xsl:call-template name="add-font-family"/>
      </xsl:attribute>
    </p>
  </xsl:template>

  <xsl:template match="another">
    <another-result>
      <xsl:attribute name="style">
        <xsl:text>text-indent:30mm; margin-top: 5mm;</xsl:text>
        <xsl:text>margin-bottom: 0; line-height:12mm;</xsl:text>
        <xsl:call-template name="add-font-family"/>
      </xsl:attribute>
    </another-result>
  </xsl:template>

  <xsl:template name="add-font-family">
    <xsl:choose>
      <xsl:when test="lang('sa')">font-family: 'Times Ext Roman';</xsl:when>
      <xsl:when test="lang('zh')"
                >font-family: Mincho,MingLiU, Batang, Simsun;</xsl:when>
      <xsl:when test="lang('ko')">font-family: Batang, BatangChe;</xsl:when>
    </xsl:choose>
  </xsl:template>

Or if the indentation and other properties are based on attributes, then make the style attribute building yet more piecemeal:

  <xsl:template match="p">
    <p>
      <xsl:attribute name="style">
        <xsl:call-template name="add-margins"/>
        <xsl:call-template name="add-font-family"/>
      </xsl:attribute>
    </p>
  </xsl:template>

  <xsl:template match="another">
    <another-result>
      <xsl:attribute name="style">
        <xsl:call-template name="add-margins"/>
        <xsl:call-template name="add-font-family"/>
      </xsl:attribute>
    </another-result>
  </xsl:template>

  <xsl:template name="add-margins">
    <xsl:choose>
      <xsl:when test="@render='this'">
        <xsl:text>text-indent:12mm; margin-top: 0;</xsl:text>
        <xsl:text>margin-bottom: 0; line-height:9mm;</xsl:text>
      </xsl:when>
      <xsl:when test="@render='that'">
        <xsl:text>text-indent:30mm; margin-top: 5mm;</xsl:text>
        <xsl:text>margin-bottom: 0; line-height:12mm;</xsl:text>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

And when you then find after distilling all of this out that you are always building your style attribute the same way based on added attributes, you can localize the entire processing along the lines of:

  <xsl:template match="p">
    <p>
      <xsl:call-template name="add-style"/>
    </p>
  </xsl:template>

  <xsl:template match="another">
    <another-result>
      <xsl:call-template name="add-style"/>
    </another-result>
  </xsl:template>

  <xsl:template name="add-style">
    <xsl:attribute name="style">
      <!--what is the margin component-->
      <xsl:choose>
        <xsl:when test="@render='this'">
          <xsl:text>text-indent:12mm; margin-top: 0;</xsl:text>
          <xsl:text>margin-bottom: 0; line-height:9mm;</xsl:text>
        </xsl:when>
        <xsl:when test="@render='that'">
          <xsl:text>text-indent:30mm; margin-top: 5mm;</xsl:text>
          <xsl:text>margin-bottom: 0; line-height:12mm;</xsl:text>
        </xsl:when>
      </xsl:choose>

      <!--what is the language component-->
      <xsl:choose>
        <xsl:when test="lang('sa')">font-family: 'Times Ext Roman';</xsl:when>
        <xsl:when test="lang('zh')"
                  >font-family: Mincho,MingLiU, Batang, Simsun;</xsl:when>
        <xsl:when test="lang('ko')">font-family: Batang, BatangChe;</xsl:when>
      </xsl:choose>
    </xsl:attribute>
  </xsl:template>

There is a myriad of different approaches you can take based on what your needs are for flexibility and how you want to signal the differences. It feels like you keep changing your requirements in your question, each time claiming that the language is "inefficient" or can't do what you want. XSLT is a very powerful and flexible language. If you want to generate different attributes algorithmically, you can. If you want to generate attribute content algorithmically, you can. If you want to layer the interpretation of input attributes, you can. If you want to construct the result in a piecemeal fashion, you can.

Different strokes for different folks ... some people like the monolithic approaches and don't mind incurring the maintenance overhead ... others like the piecemeal approach where there is only one place where a particular decision is made.

I hope this helps.

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

--
XSLT/XQuery/XPath training after http://XMLPrague.cz 2010-03-15/19
XSLT/XQuery/XPath training:   San Carlos, California 2010-04-26/30
Vote for your XML training:   http://www.CraneSoftwrights.com/s/i/
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video lesson:    http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18
Video overview:  http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18
G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal

Current Thread