Search code examples
htmlxmlxslt-1.0

Why is this transform of XML / CSS / JPG using XSL to HTML not working?


Note sure how to make one of your online test environments for this issue.

Test XSL script:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" version="4.01"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
  <xsl:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <xsl:attribute name="lang">
        <xsl:value-of select="//Settings//LanguageCode"/>
      </xsl:attribute>
      <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
        <link rel="stylesheet" type="text/css">
          <xsl:attribute name="href">
            <xsl:value-of select="//Settings/Template/@Style"/>
          </xsl:attribute>
        </link>
        <title>
          <!--<xsl:value-of select="//Labels/ReportTitleWorksheets"/>-->
          Assignment Slips
        </title>
        <style type="text/css">
          @import url('<xsl:text>2020/</xsl:text><xsl:value-of select="//Settings/Template/@Style"/>');
        </style>
      </head>
      <body>
        <xsl:for-each select="AssignmentSlips/Page">
          <div class="containerPage">
            <xsl:if test="@PageBreakBefore=1">
              <br style="page-break-before: always;"/>
            </xsl:if>
            <xsl:for-each select="StudentSlip">
              <div class="containerSlip">
                <img alt="s89" width="323px" height="429px">
                  <xsl:attribute name="src">
                    <xsl:text>2020\</xsl:text>
                    <xsl:value-of select="//Settings/Template"/>
                  </xsl:attribute>
                </img>
                <div class="fieldName">
                  <xsl:attribute name="dir">
                    <xsl:value-of select="//Settings/Direction"/>
                  </xsl:attribute>
                  <xsl:value-of select="Student"/>
                </div>
                <div class="fieldAssisant">
                  <xsl:attribute name="dir">
                    <xsl:value-of select="//Settings/Direction"/>
                  </xsl:attribute>
                  <xsl:value-of select="Assistant"/>
                </div>
                <div class="fieldDate">
                  <xsl:attribute name="dir">
                    <xsl:value-of select="//Settings/Direction"/>
                  </xsl:attribute>
                  <xsl:value-of select="Date"/>
                </div>
                <div class="fieldCounsel">
                  <xsl:choose>
                    <xsl:when test="@ItemPosition='1' and Assistant!=''">
                      <xsl:text>1st: </xsl:text>
                    </xsl:when>
                    <xsl:when test="@ItemPosition='2'">
                      <xsl:text>2nd: </xsl:text>
                    </xsl:when>
                    <xsl:when test="@ItemPosition='3'">
                      <xsl:text>3rd: </xsl:text>
                    </xsl:when>
                  </xsl:choose>
                  <xsl:attribute name="dir">
                    <xsl:value-of select="//Settings/Direction"/>
                  </xsl:attribute>
                  <xsl:value-of select="StudyPoint"/>
                </div>

                <xsl:choose>
                  <xsl:when test="Assignment=1">
                    <div class="checkBibleReading">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=2">
                    <div class="checkInitialCall">✓</div>
                    <div class="fieldInitialCallIndex">
                      <xsl:choose>
                        <xsl:when test="@ItemPosition='1'">
                          <xsl:text>#1</xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='2'">
                          <xsl:text>#2</xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='3'">
                          <xsl:text>#3</xsl:text>
                        </xsl:when>
                      </xsl:choose>
                    </div>
                  </xsl:when>
                  <xsl:when test="Assignment=3">
                    <div class="checkFirstReturnVisit">✓</div>
                    <div class="fieldFirstReturnVisitIndex">
                      <xsl:choose>
                        <xsl:when test="@ItemPosition='1'">
                          <xsl:text>#1</xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='2'">
                          <xsl:text>#2</xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='3'">
                          <xsl:text>#3</xsl:text>
                        </xsl:when>
                      </xsl:choose>
                    </div>
                  </xsl:when>
                  <xsl:when test="Assignment=4">
                    <div class="checkSecondReturnVisit">✓</div>
                    <div class="fieldSecondReturnVisitIndex">
                      <xsl:choose>
                        <xsl:when test="@ItemPosition='1'">
                          <xsl:text>#1</xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='2'">
                          <xsl:text>#2</xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='3'">
                          <xsl:text>#3</xsl:text>
                        </xsl:when>
                      </xsl:choose>
                    </div>
                  </xsl:when>
                  <xsl:when test="Assignment=5">
                    <div class="checkThirdReturnVisit">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=6">
                    <div class="checkBibleStudy">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=7">
                    <div class="checkTalk">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=0">
                    <div class="checkOther">✓</div>
                    <div class="fieldOther">
                      <xsl:attribute name="dir">
                        <xsl:value-of select="//Settings/Direction"/>
                      </xsl:attribute>
                      <xsl:value-of select="Other"/>
                    </div>
                  </xsl:when>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="Location=1">
                    <div class="checkMainHall">✓</div>
                  </xsl:when>
                  <xsl:when test="Location=2">
                    <div class="checkAuxClass1">✓</div>
                  </xsl:when>
                  <xsl:when test="Location=3">
                    <div class="checkAuxClass2">✓</div>
                  </xsl:when>
                </xsl:choose>
              </div>
            </xsl:for-each>
          </div>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Test XML data:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="AssignmentSlips-2020-v1.xsl"?>
<AssignmentSlips Version="230800">
    <Settings>
        <LanguageCode>zu</LanguageCode>
        <Template Style="s-89-zul.css">s-89-zul.jpg</Template>
        <Direction>ltr</Direction>
        <ForeignGroupMode>0</ForeignGroupMode>
    </Settings>
    <Page PageBreakBefore="0">
        <StudentSlip ItemPosition="0">
            <Student></Student>
            <StudyPoint></StudyPoint>
            <Material></Material>
            <Assignment ItemCount="1">1</Assignment>
            <Location>1</Location>
            <Date>ULwesine 9 Februwari 2023</Date>
        </StudentSlip>
        <StudentSlip ItemPosition="1">
            <Student></Student>
            <StudyPoint></StudyPoint>
            <Assignment ItemCount="1">2</Assignment>
            <Location>1</Location>
            <Date>ULwesine 9 Februwari 2023</Date>
        </StudentSlip>
        <StudentSlip ItemPosition="2">
            <Student></Student>
            <StudyPoint></StudyPoint>
            <Assignment ItemCount="1">3</Assignment>
            <Location>1</Location>
            <Date>ULwesine 9 Februwari 2023</Date>
        </StudentSlip>
        <StudentSlip ItemPosition="3">
            <Student></Student>
            <StudyPoint></StudyPoint>
            <Material></Material>
            <Assignment ItemCount="1">6</Assignment>
            <Location>1</Location>
            <Date>ULwesine 9 Februwari 2023</Date>
        </StudentSlip>
    </Page>
</AssignmentSlips>

The referenced CSS / JPG files are in a 2020 sub folder:

https://www.dropbox.com/s/vbbqr10gbgmil8s/2020.zip?dl=0

When I open the XML file with Microsoft Edge the display is blank.

When I did manage to view the source it was cropped:

<!DOCTYPE html PUBLIC "//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="zu" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <link rel="stylesheet" type="text/css" href="s-89-zul.css" />
    <title>
          Assignment Slips
        </title>
    <style type="text/css">
          @import url('2020/s-89-zul.css');
        </style>
  </head>
  <body>
    <div class="containerPage">
      <div class="containerSlip">
        <img alt="s89" width="323px" height="429px" src="2020\s-89-zul.jpg" />
        <div class="fieldName" dir="ltr">
        </div>
        <div class="fieldAssisant" dir="ltr">
        </div>
        <div class="fieldDate" dir="ltr">ULwesine 9 Februwari 2023</div>
        <div class="fieldCounsel" dir="ltr">
        </div>
        <div class="checkBibleReading">✓</div>
        <div class="checkMainHall">✓</div>
      </div>
      <div class="containerSlip">
        <img alt="s89" width="323px" height="429px" src="2020\s-89-zul.jpg" />
        <div class="fieldName" dir="ltr">
        </div>
        <div class="fieldAssisant" dir="ltr">
        </div>
        <div class="fieldDate" dir="ltr">ULwesine 9 Februwari 2023</div>
        <div class="fieldCounsel" dir="ltr">
        </div>
        <div class="checkInitialCall">✓</div>
        <div class="fieldInitialCallIndex">#1</div>
        <div class="checkMainHall">✓</div>
      </div>
      <div class="containerSlip">
        <img alt="s89" width="323px" height="429px" src="2020\s-89-zul.jpg" />
        <div class="fieldName" dir="ltr">
        </div>
        <div class="fieldAssisant" dir="ltr">
        </div>
        <div class="fieldDate" dir="ltr">ULwesine 9 Februwari 2023</div>
        <div class="fieldCounsel">2nd: 

What have I done wrong here?


Solution

  • Your first problem is that you are testing this code in an environment that gives very poor diagnostics. Ideally, test your code in an XSLT development tool such as Oxygen. If you can only test it in the browser, use a browser like Chrome with a decent developer's console.

    When I run it in XSLTfiddle (https://www.xsltfiddle.liberty-development.net) I get a clear error message:

    Error executing XSLT at line 70 : An attribute node (dir) cannot be created after a child of the containing element. Most recent element start tag was output at line 58 of module

    If you look at the surrounding code:

    <div class="fieldCounsel">
      <xsl:choose>
        <xsl:when test="@ItemPosition='1' and Assistant!=''">
          <xsl:text>1st: </xsl:text>
        </xsl:when>
        <xsl:when test="@ItemPosition='2'">
          <xsl:text>2nd: </xsl:text>
        </xsl:when>
        <xsl:when test="@ItemPosition='3'">
          <xsl:text>3rd: </xsl:text>
        </xsl:when>
      </xsl:choose>
      <xsl:attribute name="dir">
        <xsl:value-of select="//Settings/Direction"/>
      </xsl:attribute>
      <xsl:value-of select="StudyPoint"/>
    </div>
    

    It's perfectly clear that the xsl:choose is creating a text node, and you then follow this with an instruction that creates an attribute. You need to create the attributes of an element before you create the children.