'Creating and understanding XML transform

I am trying to brush up on my XML skills and was taking a course on it. There is one where I am tasked to create a XML transform from an XML instance that contains APA and MLA citations.

This is where I am stuck, I have set up my XPaths but, not sure if they are set up properly. Also looking at the transform provided to me I am not sure where to put each value-of statement to get the correct results.

Any help and explanation would be greatly appreciated!

My Code:

<?xml version="1.0" encoding="UTF-8"?>
<bibliography xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="bibliography.xsd" styleToOutput="APA and MLA">
    <article>
        <authors>
            <author>
                <lastName>Devine</lastName>
                <otherNames>Patricia G.</otherNames>
                <otherInitials>P.G.</otherInitials>
            </author>
            <author>
                <lastName>Sherman</lastName>
                <otherNames>Steven J.</otherNames>
                <otherInitials>S.J.</otherInitials>
            </author>
        </authors>
        <title>Intuitive Versus Rational Judgment and the Role of Stereotyping in the Human Condition: Kirk or Spock?</title>
        <parent type="Periodical">
            <title>Psychological Inquiry</title>
            <volume>3</volume>
            <number>2</number>
            <date>1992</date>
            <pages>153-159</pages>
        </parent>
    </article>
</bibliography>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output encoding="UTF-8" method="xml" omit-xml-declaration="yes"/>
  <xsl:template match="/">
    <html>
      <head>
        <title>Bibliography Formatter</title>
      </head>
      <body>
    <h1>Output in <xsl:value-of select="bibliography/@styleToOutput"/> Style</h1>
    <xsl:for-each select="//article">
          <xsl:if test="contains(/bibliography/@styleToOutput, 'APA')">
            <h2>APA Style</h2>
            <p>
              <xsl:for-each select="/parent">
                <xsl:if test="position()!=last()">, &amp; </xsl:if>
              </xsl:for-each> (). <xsl:value-of select="/title"/><xsl:text> </xsl:text>
              <i></i>,  </p>
          </xsl:if>
          <xsl:if test="contains(/bibliography/@styleToOutput, 'MLA')">
            <h2>MLA Style</h2>
            <p>
              <xsl:for-each select="/authors/author">
                <xsl:choose>
                  <xsl:when test="position()=1">
                  </xsl:when>
                  <xsl:otherwise>, and <xsl:text> </xsl:text>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:for-each></p>
          </xsl:if>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>


Expected output enter image description here



Solution 1:[1]

The code below doesn't do pixel-perfect render, but you should get the idea and complete it the way you need.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="UTF-8" method="xml" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <html>
            <head>
                <title>Bibliography Formatter</title>
            </head>
            <body>
                <h1>Output in <xsl:value-of select="bibliography/@styleToOutput"/> Style</h1>
                <xsl:for-each select="//article">
                    <xsl:if test="contains(/bibliography/@styleToOutput, 'APA')">
                        <h2>APA Style</h2>
                        <p>
                            <xsl:call-template name="drawAuthors"/>
                            <xsl:for-each select="parent">
                                <xsl:if test="position()!=last()">, &amp; </xsl:if>
                            </xsl:for-each> (). <xsl:value-of select="title"/><xsl:text> </xsl:text>
                            <i></i>,  </p>
                    </xsl:if>
                    <xsl:if test="contains(/bibliography/@styleToOutput, 'MLA')">
                        <h2>MLA Style</h2>
                        <p>
                            <xsl:call-template name="drawAuthors"/>                            
                            <xsl:value-of select="title"/>
                        </p>
                    </xsl:if>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
    
    <xsl:template name="drawAuthors">
        <xsl:for-each select="authors/author">
            <xsl:choose>
                <xsl:when test="position()=1">
                </xsl:when>
                <xsl:otherwise>, and <xsl:text> </xsl:text>
                </xsl:otherwise>
            </xsl:choose>                                
            <xsl:value-of select="lastName"/>
            <xsl:value-of select="otherInitials"/>
        </xsl:for-each>
    </xsl:template>
    
</xsl:stylesheet>

Solution 2:[2]

I would use mode's like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output encoding="UTF-8" method="html" indent="yes" />
  <xsl:strip-space elements="*"/>
  <xsl:variable name="styleOutput" select="/bibliography/@styleToOutput"/>
  <xsl:variable name="useModeMLA" select="contains(/bibliography/@styleToOutput, 'MLA')"/>
  <xsl:template match="/">
    <html>
      <head>
        <title>Bibliography Formatter</title>
      </head>
      <body>
        <h1>Output in <xsl:value-of select="$styleOutput"/> Style</h1>
        <xsl:if test="contains($styleOutput, 'APA')">
          <h2>APA Style</h2>
          <xsl:apply-templates mode="APA"/>
        </xsl:if>
        <xsl:if test="contains($styleOutput, 'MLA')">
          <h2>MLA Style</h2>
          <xsl:apply-templates mode="MLA"/>
        </xsl:if>
      </body>
    </html>
  </xsl:template>
  
  <xsl:template match="article" mode="APA">
    <p>
      <xsl:apply-templates select="authors/author" mode="APA"/>
      <xsl:text>. </xsl:text>
      <xsl:apply-templates select="parent/date" mode="APA"/>
      <xsl:value-of select="title"/>
      <xsl:apply-templates select="parent" mode="APA"/>
      <xsl:text>.</xsl:text>
    </p>
  </xsl:template>

  <xsl:template match="author" mode="APA">
    <xsl:if test=" position()=last()">
      <xsl:text>, &amp; </xsl:text>
    </xsl:if>
    <xsl:value-of select="concat(lastName,', ',otherInitials)"/>
  </xsl:template>

  <xsl:template match="date" mode="APA">
    <xsl:value-of select="concat('(',.,'). ')"/>
  </xsl:template>
  
  <xsl:template match="parent" mode="APA">
    <i>
      <xsl:value-of select="title"/>
    </i>
    <xsl:value-of select="concat(' , ',volume,' (',number,'), ',pages)"/>
  </xsl:template>
  
  <xsl:template match="article" mode="MLA">
    <p>
      <xsl:apply-templates select="authors/author" mode="MLA"/>
      <xsl:text>. </xsl:text>
      <xsl:value-of select="title"/>
      <xsl:apply-templates select="parent" mode="MLA"/>
      <xsl:text>.</xsl:text>
    </p>
  </xsl:template>

  <xsl:template match="author" mode="MLA">
    <xsl:if test=" position()=last()">
      <xsl:text>, and </xsl:text>
    </xsl:if>
    <xsl:value-of select="concat(lastName,', ',otherNames)"/>
  </xsl:template>
  
  <xsl:variable name="quote">"</xsl:variable>
  <xsl:template match="parent" mode="MLA">
    <i>
      <xsl:value-of select="concat($quote,title,$quote)"/>
    </i>
    <xsl:value-of select="concat(' , ',volume,'.',number,' (',date,'): ',pages)"/>
  </xsl:template>
  
</xsl:stylesheet>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Pavel Koryakin
Solution 2 Siebe Jongebloed