【问题标题】:Using XSLT to create SVG使用 XSLT 创建 SVG
【发布时间】:2014-09-26 07:25:15
【问题描述】:

我有一个存储学校班级数据的 XML 文件。我刚刚开始搞乱 SVG,所以制作了一个 SVG 文件来表示每个班级的注册人数。这是我想出的缩小版:

第一个条形代表第一个班级的 25 名学生,依此类推。

由于我还学习了一些基本的 XSLT,我想看看我是否可以从下面发布的 XML 文件中提取这些注册号,而不是手动输入这些数字(就像我在上面创建图像时所做的那样) 因为这太容易了。那就是我遇到麻烦的地方。我相信大部分信息都是正确的,但是如果您查看下面的 XSLT 文件,您会看到我将每个矩形的高度设置为 15,我想将其乘以注册号(所以第一个条的高度应该是 15*25,其中 25 是通过 XSLT 从 XML 文件中提取的。第二个条应该是 15*20,因为第二个班级的注册人数是 20,依此类推)。我一开始很好,我想我已经接近了,但是在我开始添加模板之后,条形消失了。任何帮助将不胜感激!

当前 XSLT 文件:

<?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 文件:

<?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>

编辑:

这是 SVG 代码在 XSLT 转换后的样子:

<?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>

重申一下,每个矩形的高度都应该是注册人数乘以 15(否则矩形条会太短)。我也希望它按顺序排列,所以第一个条应该是第一个注册号乘以 15,最后一个条应该是最后一个注册号乘以 15。

【问题讨论】:

  • 我正在尝试使用 XSLT 重新创建上面的相同图像,以防不完全清楚。
  • 我认为您不需要为每个栏使用单独的模板。您可能不知道那里有多少部分,即使您知道,这样的编码也是不必要的重复。使用 position() 函数计算条形的 x 坐标,并根据 enrollment 的值计算其高度。 -- 另请注意,您指的是这里不存在的东西:y="{500-@height}"
  • 为了使矩形的底部与水平红线对齐,我需要从 500 中减去高度。或者是否有其他方法可以确保它们与水平线对齐?
  • 你能把你在作为代码之后的结果贴出来吗?
  • 所需的 SVG 代码已添加到我的帖子底部。

标签: xml xslt svg


【解决方案1】:

让我建议以下几点作为您的出发点:

<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>

另请参阅: Using XSLT and SVG to create bar chart from XML - Scaling Bar Chart

【讨论】:

  • 完美,我绝对可以使用它。谢谢!
【解决方案2】:

确保将 SVG 命名空间的声明放在样式表的根元素上,因为只有这样它才会应用于所有模板中的所有结果元素。使用您当前的代码,只有 svg 元素获得正确的命名空间,而其他模板中的矩形最终不在命名空间中。

【讨论】:

  • 好收获。感谢您的提示,但不幸的是,我的代码仍然无法正常工作。
  • y 属性使用表达式 @height 但该属性未在您发布的输入示例中定义。
  • 当我这样写时,它是否试图从 XML 文件中提取高度属性?我希望它减去在 XSLT 文件中同一个矩形内声明的 height 属性的值,就在 Y 属性右侧的一点点处。看起来像这样:height="{15*.}"
  • 如果高度变大而 Y 属性保持不变,那么矩形的定位就搞砸了。
  • 定义一个变量&lt;xsl:variable name="height" select="15 * ."/&gt;,然后使用y="500 - $height"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-17
  • 2014-04-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多