Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
799 views
in Technique[技术] by (71.8m points)

xml - Using XSLT to create SVG

I have an XML file that stores data about classes at a school. I'm just starting to mess around with SVG, so made an SVG file to represent the enrollment numbers in each class. Here's a shrunken version of what I came up with:

enter image description here

The first bar represents the 25 students enrolled in the first class and so on.

Since I've also learned some basic XSLT, I'd like to see if I can pull in those enrollment numbers from the XML file posted below instead of just putting the numbers in manually (like I did to create the image above) since that is too easy. That is where I'm having trouble. I have most of the info correct I believe, but if you take a look at my XSLT file below, you'll see I have the height of each rectangle set to 15 and I would like to multiply that by the enrollment number (so the height of the first bar should be 15*25, with the 25 being pulled from the XML file via XSLT. The second bar should be 15*20, since the enrollment of the second class is 20, and so on). I started out well and I think I'm close, but after I started adding templates, the bars disappeared. Any help would be appreciated!

Current XSLT file:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- main template -->
  <xsl:template match="/">
    <!-- root element is svg and its namespace -->
    <svg version="1.0"
     xmlns="http://www.w3.org/2000/svg">


        <!-- Vertical red line -->
        <line x1="30" y1="35" x2="30" y2="500"
        style="stroke:rgb(255,0,0);stroke-width: 3" />
        <!-- Horizontal red line -->
        <line x1="30" y1="500" x2="500" y2="500"
        style="stroke:rgb(255,0,0);stroke-width: 3" />

        <!-- apply templates to display rectangle bars-->
        <xsl:apply-templates select="courses/course/enrollment" />
      </svg>
  </xsl:template>

        <!-- Rectangle 1 template -->
        <xsl:template match="enrollment[1]">
        <!-- Blue Rectangle 1 (341-01) -->
        <rect x="40" y="{500-@height}" width="30" height="{15*.}"
        style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" />
        </xsl:template>

        <!-- Rectangle 2 template -->
        <xsl:template match="enrollment[2]">
        <!-- Blue Rectangle 2 (341-02) -->
        <rect x="100" y="{500-@height}" width="30" height="{15*.}"
        style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" />
        </xsl:template>

        <!-- Rectangle 3 template -->
        <xsl:template match="enrollment[3]">
        <!-- Blue Rectangle 3 (341-03) -->
        <rect x="160" y="{500-@height}" width="30" height="{15*.}"
        style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" />
        </xsl:template>

           <!-- Rectangle 4 template -->
        <xsl:template match="enrollment[4]">
        <!-- Blue Rectangle 4 (368-01) -->
        <rect x="220" y="{500-@height}" width="30" height="{15*.}"
        style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" />
        </xsl:template>

           <!-- Rectangle 4 template -->
        <xsl:template match="enrollment[4]">
        <!-- Blue Rectangle 5 (375-01) -->
        <rect x="280" y="{500-@height}" width="30" height="{15*.}"
        style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" />
        </xsl:template>

           <!-- Rectangle 4 template -->
        <xsl:template match="enrollment[4]">
        <!-- Blue Rectangle 6 (385-01) -->
        <rect x="340" y="{500-@height}" width="30" height="{15*.}"
        style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" />
        </xsl:template>

           <!-- Rectangle 5 template -->
        <xsl:template match="enrollment[5]">
        <!-- Blue Rectangle 7 (413-01) -->
        <rect x="400" y="{500-@height}" width="30" height="{15*.}"
        style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" />
        </xsl:template>
  </xsl:stylesheet>

XML file:

<?xml version="1.0" encoding="UTF-8"?>
<courses>
  <course number="3221" credits="4.0">
    <title>Physics</title>
    <section number="01" delivery="Classroom">
      <enrollment>25</enrollment>
      <room>EA244</room>
      <instructor>
        <first>Herman</first>
        <last>Johnson</last>
      </instructor>
    </section>
    <section number="02" delivery="Online">
      <enrollment>20</enrollment>
      <instructor>
        <first>Herman</first>
        <last>Johnson</last>
      </instructor>
      <instructor>
        <first>Mike</first>
        <last>Miller</last>
      </instructor>
    </section>
    <section number="03" delivery="Classroom">
      <enrollment>12</enrollment>
      <room>SH102</room>
      <instructor>
        <first>Allison</first>
        <last>Sweeney</last>
      </instructor>
    </section>
  </course>
  <course number="1318" credits="4.0">
      <title>Psychology</title>
    <section number="01" delivery="Classroom">
      <enrollment>9</enrollment>
      <room>AT102</room>
      <instructor>
        <first>Mike</first>
        <last>Miller</last>
      </instructor>
      <instructor>
        <first>Alex</first>
        <last>Holmquist</last>
      </instructor>
    </section>
  </course>
  <course number="3715" credits="4.0">
      <title>Biology</title>
    <section number="01" delivery="ITV">
      <enrollment>18</enrollment>
            <room>EA244</room>
      <instructor>
        <first>Mike</first>
        <last>Miller</last>
      </instructor>
    </section>
  </course>
  <course number="3815" credits="3.0">
      <title>Calculus</title>
    <section number="01" delivery="Classroom">
      <enrollment>16</enrollment>
            <room>ST108</room>
      <instructor>
        <first>Herman</first>
        <last>Johnson</last>
      </instructor>
    </section>
  </course>
  <course number="4113" credits="3.0">
      <title>Chemistry</title>
    <section number="01" delivery="Online">
      <enrollment>20</enrollment>
      <instructor>
        <first>Mike</first>
        <last>Miller</last>
      </instructor>
    </section>
  </course>
</courses>

EDIT:

Here is what the SVG code should look like after the XSLT transformation:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.0">

   <line style="stroke:rgb(255,0,0);stroke-width: 3" y2="500" x2="30" y1="35" x1="30" />
   <line style="stroke:rgb(255,0,0);stroke-width: 3" y2="500" x2="500" y1="500" x1="30" />
   <rect style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" height="375" width="30" y="125" x="40" />
   <rect style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" height="300" width="30" y="200" x="100" />
   <rect style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" height="180" width="30" y="320" x="160" />
   <rect style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" height="135" width="30" y="365" x="220" />
   <rect style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" height="270" width="30" y="230" x="280" />
   <rect style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" height="240" width="30" y="260" x="340" />
   <rect style="fill:rgb(255,0,0);stroke-width: 3;stroke:rgb(0,0,0)" height="300" width="30" y="200" x="400" />
</svg>

To reiterate, the height of each rectangle should come from whatever the enrollment number is multiplied by 15 (otherwise the rectangle bars will be too short). I would also like it to go in order, so the first bar should be the first enrollment number times 15, and the last bar should be the last enrollment number times 15.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Let me suggest the following as your starting point:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg">

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <svg version="1.0"> 
        <g transform="translate(0 500) scale(1 -1)">
            <xsl:apply-templates select="courses/course/section"/>
        </g>
    </svg>
</xsl:template>

<xsl:template match="section">
    <rect x="{40 * position()}" width="30" height="{enrollment}"/>
</xsl:template>

</xsl:stylesheet>

See also: Using XSLT and SVG to create bar chart from XML - Scaling Bar Chart


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...