JavaEnterprise JavaWriting Java Servlets to Produce XHTML Code That References External SVG Files

Writing Java Servlets to Produce XHTML Code That References External SVG Files

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Java Programming Notes # 2218


Preface

General

This lesson is part of a series (see Resources)
designed to teach you how to write servlets to produce SVG code that will be
rendered in graphic form by an SVG-capable browser such as Firefox 1.5.  In this lesson you will
learn how to write servlets that produce XHTML output containing references to
external SVG files.  The SVG files may be static, or may be created on-the-fly during the
execution of the servlet.

An SVG graphics library

I taught you how write your own SVG
graphics library to eliminate, or at least alleviate the requirement to write
raw XML code or raw JAXP DOM code in earlier lessons in the series.  The use of the SVG graphics library makes it
possible for you to produce SVG output simply by making typical Java method
calls.  One of the sample programs in this lesson makes use of that SVG
graphics library.

Viewing tip

I recommend that you open another copy of this document in a separate
browser window and use the following links to easily find and view the figures
and listings while you are reading about them.

Figures

  • Figure 1. Graphic output for all three programs.
  • Figure 2. Output XHTML produced by the program
    Svg09.
  • Figure 3. Five steps for writing a servlet
    program.

Listings

Supplementary material

I recommend that you also study the other lessons in my extensive collection
of online Java tutorials.  You will find a consolidated index at

www.DickBaldwin.com
.

General background information

SVG is a language for describing two-dimensional graphics in XML. SVG allows
for three types of graphic objects:

  • vector graphic shapes
  • images
  • text

The Scalable Vector Graphics (SVG) 1.1
Specification
is extensive, but it is not easy reading, particularly if your
knowledge of XML is weak.

While I don’t claim to be an expert in XML, I do know enough about the topic
that I can usually make sense of the material provided in the SVG
specification.  One of my objectives for this series is to help Java programmers
who lack a strong background in XML take advantage of the capabilities of SVG.

Great graphics in the browser

 

No experience with IE/SVG plug-in
The SVG rendering engines that are available include Firefox
1.5.  I have also read that IE can be made SVG capable by
installing an SVG plug-in.   Please note however that I have not
installed and tested the SVG plug-in for IE.  The sample
programs in this series were tested using Firefox 1.5.

You can write Java programs that will produce XML output, which, when loaded
into an SVG rendering engine, will result in the display of rich graphic
material.  When combined with the use of servlets, this makes it possible to
display graphic material in the client area of a web browser that competes
favorably with the graphic material that can be displayed using the Java 2D API
(see Resources) in desktop
applications.

Preview

A desktop application

I will present and explain three different programs in this lesson.  The
first program, named Svg09 is a stand-alone desktop application that
produces an output XHTML file, (which will validate at

http://validator.w3.org/file-upload.html
)
.  When this XHTML file is
loaded into an SVG-capable browser, (such as Firefox 1.5), it references
an SVG file stored in the same directory and causes the graphic contents of the
SVG file to be rendered by the browser.

This program is mainly a first step towards the writing of servlets that
produce XHTML data that serves SVG files.  I will present and explain this
program first because it is much easier to test and debug desktop applications than it
is to test and debug servlets.  As I demonstrated in the earlier lesson
titled "Using Java to produce SVG code in XHTML data" (see
Resources)
, once you finish writing, testing, and
debugging a desktop application, it is not a difficult task to convert it a
servlet.

A servlet that serves a static SVG file

The second program named Svg10 is a Java servlet program that delivers
XHTML data, which, in turn references a static SVG file stored on the server. 
When this servlet is accessed using Firefox 1.5, the static SVG file is accessed
and the graphic contents of the file are rendered by the browser. 

The XHTML output produced by this servlet will validate at

http://validator.w3.org/file-upload.html
.

Something a little more dynamic

A word of caution.
Although this approach is interesting, you should probably be very
careful how you apply it.  I can foresee some problems if the approach
is used in a multi-client situation without proper protection against the
possibility of conflicts regarding access to the SVG file.

The third program named Svg11 is similar to Svg10, with the
major exception that it first creates an SVG file and stores it on the server
and then delivers XHTML data that references that new SVG file.  When this
servlet is accessed using Firefox 1.5, the new SVG file is accessed and the
graphic contents of the file are rendered by the browser.

The output
produced by this servlet will also validate at

http://validator.w3.org/file-upload.html
.

The graphic output

Actual graphic output.
The actual graphic output produced by the first two programs isn’t too
important, because that output is the rendering of a previously generated
SVG file.  The actual graphic output is important only for the third
program because that program creates the SVG file that is served by the
servlet on-the-fly as the servlet is executing.

All three programs produce the same graphic output, which is shown
in Figure 1.

The first two programs require the availability of a previously
generated SVG file.  Hopefully, by now, you know how to write your own Java
programs to create SVG files.  Or, you can create an SVG file by
executing the program named Svg08, that I explained in the earlier lesson
titled "An improved approach for creating SVG/XML code and SVG/XML DOM nodes
using Java" (see Resources).

Figure 1. Graphic output for all three programs.

The graphic image shown in Figure 1 is the same image that I explained in the
earlier lesson titled "Using Java to produce SVG code in XHTML data" (see
Resources)
.  I will explain later how the
scrollbars and the text in Figure 1 were produced.

Discussion
and sample code

The program named Svg09

Description of the program

The purpose of
this program is to show you how to write a Java program that creates an XHTML
file, which references a static SVG graphics file stored in the same directory
on the local hard disk.

As I mentioned earlier, my main reason for showing you this desktop
application first is because desktop applications are much easier to test and debug
than servlets.  Further, once you have the desktop application running
correctly, it is not very difficult to convert it to a servlet.

Three ways to reference a static SVG file

There are at least three ways to write the XHTML code to reference an SVG
file, each of which has
advantages and disadvantages.  (The following
information was taken from the web page titled "SVG in HTML pages." 
(See
Resources.)

<embed>

  • Advantage: supported in nearly any browser, allows html2svg and svg2html
    scripting, is recommended by Adobe for their SVG Viewer
  • Disadvantage: not clearly standardized within any HTML specification

<object>

  • Advantage: HTML4 and higher standard, supported in newer browser
    generations
  • Disadvantage: works on newer browsers but without html2svg and svg2html
    scripting.

<iframe>

  • Advantage: works in most browsers, but not documented
  • Disadvantage: generates a window-like border without specific styling

How I did it

This program embeds the reference to the SVG file in an object element. 
The XHTML output file produced by this program was tested and confirmed to be
valid at: http://validator.w3.org/ 


Output XHTML produced by the program Svg09

The XML code produced by this
program (with some line breaks manually inserted for compatibility with this
narrow publication format)
is shown in Figure 2.  I will refer back to
this output XML code later while explaining the program code.

Figure 2. Output XHTML produced by the program Svg09.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD 
XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html  xml_lang="en" >
<head>
<meta http-equiv="content-type" content="image/svg+xml; 
charset=UTF-8" />
<title>Generated XHTML file</title>
</head>
<body style="border:1px solid black;width:220px;
height:500px;" >

<p>There is an image below here.
<object type="image/svg+xml" width="210" height="430" 
data="Svg09.svg" />
There is an image above here.</p>

</body></html>

The most interesting code in Figure 2 is highlighted in boldface.

Program testing

The program was tested using J2SE 5.0 and Firefox 1.5.09, running under WinXP.


The beginning of the Svg09 class

As is my custom, I will discuss and explain this program in fragments. 
You can view a complete listing of the program named Svg09 in Listing 10
near the end of the lesson.

The beginning of the class named Svg09 is shown in Listing 1.

Listing 1. The beginning of the Svg09 class.

public class Svg09{

  public static void main(String argv[]){

    try{
      //Get an output stream.
      PrintWriter out = new PrintWriter(
                      new FileOutputStream("junk.xhtml"));
                      
      //Create the beginning text required for the XHTML
      // document.
      makeXhtmlText(out);

Get an output stream and write normal XHTML text

Listing 1 begins by getting an output stream for writing the XHTML file named
junk.xhtml.

Then it calls a convenience method named makeXhtmlText for the purpose
of writing the normal text that is required for the beginning of a valid XHTML
document.  The method named makeXhtmlText creates all of the text
above the boldface text in Figure 2.  There is nothing new about this text
or this code. 
I have discussed it in several previous lessons.  I broke this code out
into a separate method here simply for clarity.  You can view the method named
makeXhtmlText in Listing 10.


Create the object element

The makeElement method.
I first presented and explained the convenience method named makeElement in an
earlier lesson titled "An improved approach for creating SVG/XML code and
SVG/XML DOM nodes using Java" (see Resources).  The purpose of this method is to alleviate the
difficulty of dealing with the many quotation marks that are required to
surround attribute values in raw SVG/XML code.  You can view the method
in its entirety in Listing 10.

Listing 2 calls the convenience method named makeElement to insert an
object element into the output file.  The object element references an SVG file named Svg09 in the same directory.

Two lines of plain text

I promised earlier that I would explain how the
two lines of text shown in Figure 1 are produced.  Listing 2 inserts one line of plain text above and one line of plain
text below the object element.  You can view those two lines of text
above and below the area allocated for the image by Firefox in Figure 1.

Listing 2. Create the object element.

      out.println("<p>There is an image below here.");

      out.println(makeElement(
                  true,
                  "object",
                  new String[]{"type","image/svg+xml",
                               "width","210",
                               "height","430",
                               "data","Svg09.svg",
                              })//end call to makeElement
      );//end call to println
      
      out.println("There is an image above here.</p>");

The scrollbars

I also promised you earlier that I would explain the presence of the scrollbars in
Figure 1.  Well, the time for that explanation has come.

The image in the file named Svg09.svg that is rendered in Figure 1 has an
actual width of 220 pixels and an actual
height of 440 pixels.  As you can see, the values of the width and
height attributes in the object element that is created in Listing
2 are smaller than those dimensions (210 x 430 pixels).  Firefox 1.5
responds to this situation by automatically placing horizontal and vertical
scrollbars on the image as shown in Figure 1.  This makes it possible to
view the entire image by manipulating the scroll bars.


Finish writing the file and terminate the program

Listing 3 writes the final XHTML text and flushes the output buffer.

Listing 3. Finish writing the file and terminate the
program.

      out.println("</body></html>");
      out.flush();

    }catch(Exception e){
      //Note that no effort was made to provide meaningful
      // information in the event of an exception or
      // error.
      e.printStackTrace(System.err);
    }//end catch

  }// end main()

Listing 3 also signals the end of the main method.  When control
returns from the flush method, there is nothing more for the main
method to do, so the program terminates.

Not much effort required

As you can see, once you have access to the convenience methods that I have
provided, it doesn’t require much effort to write a Java program that will
produce an output XHTML file that references an SVG file, which will be rendered
when the XHTML file is loaded into Firefox 1.5.

Conversion to a servlet

In the Summary section of the lesson titled "Using Java to produce SVG code
in XHTML data" (see Resources), I explained
the list of five fairly simple steps shown in Figure 3 that are required to convert a desktop
application such as Svg09 into a servlet.

Figure 3. Five steps for writing a servlet program.

  1. Declare the following import directives:

      import javax.servlet.*;
      import javax.servlet.http.*;

  2. Define the main class to extend the HttpServlet class.
  3. Replace the signature for the main method in the desktop
    application with the signature for the doGet method in the servlet
    program:

      public void doGet(HttpServletRequest req,
                        HttpServletResponse res)
                               throws ServletException,
    	                          IOException{

  4. Execute the following statement to set the content type:

      res.setContentType("image/svg+");

  5. Execute the following statement to get an output stream:

      PrintWriter out = res.getWriter();

Will convert Svg09 into a servlet program

The next program that I will
explain will be a servlet program that serves a
static SVG file that is stored on the server.  The program named Svg10
was written by converting the program named Svg09 into a servlet.  When the servlet is accessed
using Firefox 1.5, the SVG file is retrieved and rendered.  An example
of the output using my SVG
file is shown in Figure 1.  If you use a different SVG file, you should get
a different output.

The program named Svg10

Description of the program

The purpose of this program is to show you how to write a simple servlet that
will serve a static SVG graphics file stored on a jakarta-tomcat server running
as a localhost server under WinXP.

Where should the SVG file be stored on the server?

One of the more difficult aspects of writing this servlet program had nothing
to do with Java programming.  Rather, it had to do with figuring out where
to store the SVG file on the server and how to refer to the file in the SVG/XML code so that
it would be found and retrieved by the browser.  In this regard, my
thanks go to Marty Hall at
http://www.apl.jhu.edu/~hall/
for helping me to understand:

  • Where to place static files to cause them to be accessible by a servlet.
  • How to reference those files within the servlet.

Must be tested as a servlet

This program can only be tested by deploying the servlet on a
servlet-compatible server and then accessing it using an SVG-capable browser,
such as Firefox 1.5.

For this demonstration, the static SVG file was stored in the following
location on my hard drive:

C:jakarta-tomcat-5.0.27webappsROOTimages

The servlet class file was stored in:

C:jakarta-tomcat-5.0.27webappsROOTWEB-INFclasses

The servlet was accessed by addressing the following URL with Firefox:

http://localhost/servlet/Svg10

The code produced by this servlet was tested and confirmed to be valid at:
http://validator.w3.org/

The program was tested using J2SE 5.0, Firefox 1.5.09,
and jakarta-tomcat-5.0.27 running as a localhost server under WinXP.

Will discuss in fragments

As usual, I will discuss this program in fragments.  Also as usual, the program can be
viewed in its entirety in Listing 11 near the end of the lesson.

However, because of the similarity of this program to the program named
Svg09
, I will only discuss those parts of the program that are different
from Svg09 that were required to
convert it from a desktop application to a servlet as described in the previous
list of steps.


Beginning of the program named Svg10

The beginning of the program is shown in Listing 4.

Listing 4. Beginning of the program named Svg10.

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Svg10 extends HttpServlet{

  public void doGet(HttpServletRequest req,
                    HttpServletResponse res)
                      throws ServletException,IOException{
                        
    res.setContentType("image/svg+xml");

    try{
      //Get an output stream.
      PrintWriter out = res.getWriter();

The code in Listing 4 satisfies all five steps listed in the
previous list of steps that were required to convert the
program named Svg09 into the servlet program named Svg10.  Therefore, there is nothing
more for me to discuss and explain in this program.

Therefore, that ends the discussion of the program named Svg10.

The program named Svg11

Description of the program

This program is much longer than either of the previous two programs in this
lesson.  However, there is very little that is new in this program. 
Mainly, this program was written by combining sections of code that I have
previously explained in this and earlier lessons.  Therefore, the
explanations of the code for this program will be fairly brief.

The purpose of this program is to write a servlet that will first create a
static SVG file and store it on the server and then serve that file to an
SVG-capable web client by way of XHTML code that is sent to the client.

The code to accomplish this is somewhat simpler than the code required to
create the SVG graphic code and to send it directly to the client as in-line
graphic code.  This is because this approach makes better use of JAXP to
process the DOM tree that represents the graphic image.

This program uses an SVG graphic library that has been discussed and
explained in earlier lessons on this topic.

The beginning of the program named Svg11

The program begins by:

  • Defining a servlet that: Creates a DOM tree describing the graphic image
    shown in Figure 1.
  • Transforming that tree into corresponding SVG XML code.
  • Writing the SVG code into an output file on the server named Svg11.svg.

Producing the XHTML output

Then the servlet creates the code for a short XHTML document that references
the SVG file that was just written and sends that XHTML code back to the client.

The XHTML code sent to the client is valid according to:


http://validator.w3.org/file-upload.html

Must be tested as a servlet

This program can only be tested by deploying the servlet on a
servlet-compatible server and then accessing it using an SVG-capable browser
such as Firefox 1.5.

On my system, the SVG file was written by the servlet into the following directory:

C:jakarta-tomcat-5.0.27webappsROOTimages

The servlet was tested by first copying it into the following directory on the
Tomcat server:

C:jakarta-tomcat-5.0.27webappsROOTWEB-INFclasses

Then the servlet was accessed using Firefox 1.5.09 at the URL given below:

http://localhost/servlet/Svg11

The program was tested using J2SE 5.0, Firefox 1.5.09, and
jakarta-tomcat-5.0.27 running as a localhost server under WinXP.


The beginning of the class and the doGet method

As usual, I will discuss this program in fragments.  Also, as usual, you
can view the entire program in its entirety in Listing 12 near the end of the
lesson.

Listing 5 contains some of the requisite servlet code that you saw earlier in the
program named Svg10.

Listing 5. The beginning of the class and the doGet
method.

public class Svg11 extends HttpServlet{

  public void doGet(HttpServletRequest req,
                    HttpServletResponse res)
                      throws ServletException,IOException{


Abbreviated code for creating the DOM tree

Listing 6 shows an abbreviated version of essentially the same code that
I explained in detail in Listing 1 through Listing 20 in the earlier lesson titled
"Using Java to produce SVG code in XHTML data" (see
Resources
)
.  Note that I deleted most of the code from Listing 6
for brevity, but you can view that code in its entirety in Listing 12.  The
code that is represented by Listing 6 creates a DOM tree that represents the
graphic image shown in Figure 1.

Listing 6. Abbreviated code for creating the DOM
tree.

    //The following data values will be used to create
    // SVG graphics.
    int ellipseCenterX = 110;
//...
      //Begin by creating a Document object and a root
      // node named svg.
      Document document = SvgGraphics.getDocument();      
      Element svg = SvgGraphics.makeNode(
//...
      //Create a node named defs, which will be the parent
      // for three gradient definitions.
      Element defs = SvgGraphics.makeNode(document,
//...
      //Create nodes that define three different gradient
      // coloring schemes.
      Element gradientA = SvgGraphics.makeLinearGradient(
//...
      //Create three stop nodes that identify the colors
      // used to produce the gradient and specify where
      // the colors begin and end, 
      SvgGraphics.makeGradientStop(document,
//...
      Element gradientB = SvgGraphics.makeLinearGradient(
//...
      Element gradientC = SvgGraphics.makeRadialGradient(
//...                    
      //Create a node named g, which will be the parent
      // for an ellipse,a circle, a rectangle, a line,
      // a polyline, and a polygon.
      Element g = SvgGraphics.makeNode(document,
//...
      //Create an ellipse with a blue border that is two
      // pixels wide. Fill it with the yellow-red-blue
      // gradient defined by gradientA.
      Element theEllipse = SvgGraphics.makeEllipse(
//...
      //Rotate the ellipse by 15-degrees clockwise about
      // its center.
 efeheEllipse.setAttribute("transform",
//...
      //Position a circle so that it appears to be inside
      // the ellipse.
      Element theCircle = SvgGraphics.makeCircle(
//...
      //Set the appearance of the circle and rotate it by
      // 15-degrees clockwise about its center.
      theCircle.setAttribute("fill","url(#gradientB)");
      theCircle.setAttribute("transform",
//...
      //Make a rounded rectangle and fill it with
      // gradientC
      Element theRect = SvgGraphics.makeRect(
//...
      //Draw a polyline with four points.
      int[] polylinePoints = 
                         {10,235,210,235,110,275,110,225};
      Element polyline = SvgGraphics.makePolyline(
//...
      //Rotate the polyline by 10 degrees around the first
      // point.
      polyline.setAttribute("transform",
//...
      //Draw a polygon with four points. Give it a red
      // border and fill it with green.
      int[] polygonPoints = 
                         {10,335,210,335,110,375,110,325};
      Element polygon = SvgGraphics.makePolygon(
//...
      //Draw a green line 12 pixels wide.  Make the line
      // 60% opaque, or 40% transparent, whichever you
      // prefer.
      Element line = SvgGraphics.makeLine(document,
//...


Transform the DOM tree

Listing 7 transforms the DOM tree into SVG XML code and writes that code into an SVG file on the server.

Listing 7. Transform the DOM tree.

      SvgGraphics.transformTheDom(document,
        getServletContext().getRealPath("/") + "images" 
                          + File.separator + "Svg11.svg");

The code in Listing 7 is essentially the same as the code that I explained
beginning with Listing 21 in the previous lesson titled "An improved approach
for creating SVG/XML code and SVG/XML DOM nodes using Java" (see
Resources)
with one exception.  That exception
has to do with the code required to specify the location where the SVG file will
be written.  In the earlier lesson, the file was written into the current
directory on the local hard disk.  In Listing 7, the SVG file is written
into a file on the server.

The getServletContext method

The getServletContext method is inherited into the Svg11 class by way of
the superclass named HttpServlet.  The method returns a
reference to an object of type ServletContext.  Here is part of what
Sun has to say about the getServletContext method:

"Returns a ServletContext object, which contains information about the
network service in which the servlet is running."

According to Sun, an object that implements the ServletContext
interface is:

"A servlet engine generated object that gives servlets information
about their environment."

Also according to Sun, the invocation of the getRealPath method on the
ServletContext
object:

"Returns a String representing the corresponding real
path in the format that is appropriate for the operating system the servlet
engine is running under (including the proper path separators)."

To make a long story short

To make a long story short, on my system, the execution of the getRealPath
method as shown in Listing 7 returns the following string:

C:jakarta-tomcat-5.0.27webappsROOT

The code in Listing 7 then concatenates the proper material onto the end of
that string to produce the
following string, which is where the SVG file was written by the servlet.

C:jakarta-tomcat-5.0.27webappsROOTimages

Execute some more required servlet code

By now, you should recognize the first statement in Listing 8 as the code
required to get an output stream for the XHTML text that will be sent directly from the servlet to the browser.

Listing 8. Execute some more required servlet code.

      PrintWriter out = res.getWriter();

      res.setContentType("image/svg+xml");

You should also recognize the second statement in Listing 8 as the code
required to set the type of the servlet output to the correct type for SVG data.


Create the XHTML document

The code in Listing 9 is essentially the same as the code that I explained
earlier in this lesson in Listing 1 through Listing 3.

Listing 9. Create the XHTML document.

      //Create the beginning text required for the XHTML
      // document.
      makeXhtmlText(out);
      
      //Insert an object element that references a static
      // SVG file in the directory listed in the
      // opening comments to this program. The servlet
      // also causes plain text to be displayed above and
      // below the object element.
      out.println("<p>There is an image below here.");

      out.println(SvgGraphics.makeElement(
                  true,
                  "object",
                  new String[]{"type","image/svg+xml",
                               "width","210",
                               "height","430",
                               "data","/images/Svg11.svg",
                              })//end call to makeElement
      );//end call to println
      
      out.println("There is an image above here.</p>");

      //Write the final XHTML text and flush the output
      // buffer.
      out.println("</body></html>");
      out.flush();

    }catch(Exception e){
      //Note that no effort was made to provide meaningful
      // information in the event of an exception or
      // error.
      e.printStackTrace(System.err);
    }//end catch

  }// end doGet()

End of the program

That concludes the explanation of the program named Svg11.

Run the program

I encourage you to copy the code from Listing 10, Listing 11, and Listing 12 into your text
editor, compile it, and execute it.  Then view the results in Firefox 1.5,
or some other suitable SVG rendering engine.  Experiment with the code, making
changes, and observing the results of your changes.

Above all, enjoy the process. Programming, particularly graphics programming,
can be fun.

Summary

In this lesson I taught you how to write a Java desktop application
that creates an output XHTML file containing references to an external SVG file. 
After that, I taught you how to write servlets that produce XHTML output containing
references to external SVG files.  The SVG files may be static, or may be
created on-the-fly during the execution of the servlet.

What’s next?

Future lessons in this series will teach you how to write servlets that:

  • Deal with the following graphics elements:

    • path
    • text
    • image (Deal with bit-mapped images in SVG.)
    • use (Create and re-use graphics elements.)

  • Use SVG symbols.
  • Deal with stroke caps in SVG in comparison with similar caps in Java 2D.
  • Use the switch element in SVG.
  • Deal with other features of SVG, such as animation.

Resources

Java 2D Graphics
300 Java 2D Graphics,
Nested Top-Level Classes and Interfaces 
302 Java 2D Graphics,
The Point2D Class 
304 Java 2D Graphics,
The Graphics2D Class 
306 Java 2D Graphics,
Simple Affine Transforms 
308 Java 2D Graphics,
The Shape Interface, Part 1 
310 Java 2D Graphics,
The Shape Interface, Part 2 
312 Java 2D Graphics,
Solid Color Fill 
314 Java 2D Graphics,
Gradient Color Fill 
316 Java 2D Graphics,
Texture Fill 
318 Java 2D Graphics,
The Stroke Interface 
320 Java 2D Graphics,
The Composite Interface and Transparency 
322 Java 2D Graphics,
The Composite Interface, GradientPaint, and Transparency 
324 Java 2D Graphics,
The Color Constructors and Transparency
Java 2D API
Specification

Java 2D API

Java API for XML Processing (JAXP)
2200 Java
API for XML Processing (JAXP), Getting Started
2202 Getting
Started with Java JAXP and XSL Transformations (XSLT)
2204 Java
JAXP, Exposing a DOM Tree
2206 Java
JAXP, Implementing Default XSLT Behavior in Java
2208 Java
JAXP, Writing Java Code to Emulate an XSLT Transformation
2210 Java
JAXP, Transforming XML to XHTML
Links to numerous XML tutorials
by Richard G. Baldwin

Scalable Vector Graphics (SVG)
2212 Java JAXP, Creating graphics using Java and SVG
2214 An improved approach for creating SVG/XML code and SVG/XML DOM nodes
using Java
2216 Using Java to produce SVG code in XHTML data
Scalable Vector Graphics (SVG) 1.1
Specification

Adobe SVG Viewer plug-in

Create vector graphics in the browser with SVG
by Uche Ogbuji
SVG Tutorial
SVG Basics
SVG in HTML
pages

Miscellaneous
W3C Markup Validation
Service
.

Complete program listings


Complete listings of the programs discussed in this lesson are shown in Listing
10 through Listing 12 below.

Listing 10. Program code for Svg09.

/*File Svg09.java
Copyright 2006 R.G.Baldwin

The purpose of this program is to show you how to write a 
Java program that creates an XHTML file, which references
a static SVG graphics file stored in the same directory on
the local hard disk.

There are several ways to accomplish this.  This program
embeds the reference to the SVG file in an object element.

The XHTML output file produced by this program was tested
and confirmed to be valid at:

http://validator.w3.org/

The XML code produced by this program (with some line 
breaks manually inserted for compatibility with this 
narrow publication format) is shown below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD 
XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html  xml_lang="en" >
<head>
<meta http-equiv="content-type" content="image/svg+xml; 
charset=UTF-8" />
<title>Generated XHTML file</title>
</head>
<body style="border:1px solid black;width:220px;
height:500px;" >
<p>There is an image below here.
<object type="image/svg+xml" width="210" height="430" 
data="Svg09.svg" />
There is an image above here.</p>
</body></html>

Tested using J2SE 5.0 and Firefox 1.5.09, running under 
WinXP.
*********************************************************/

import java.io.*;

public class Svg09{

  public static void main(String argv[]){

    try{
      //Get an output stream.
      PrintWriter out = new PrintWriter(
                      new FileOutputStream("junk.xhtml"));
                      
      //Create the beginning text required for the XHTML
      // document.
      makeXhtmlText(out);
      
      //Insert an object element that references an SVG
      // file in the same directory, with plain text
      // above and below the object element.
      out.println("<p>There is an image below here.");

      out.println(makeElement(
                  true,
                  "object",
                  new String[]{"type","image/svg+xml",
                               "width","210",
                               "height","430",
                               "data","Svg09.svg",
                              })//end call to makeElement
      );//end call to println
      
      out.println("There is an image above here.</p>");

      //Write the final XHTML text and flush the output
      // buffer.
      out.println("</body></html>");
      out.flush();

    }catch(Exception e){
      //Note that no effort was made to provide meaningful
      // information in the event of an exception or
      // error.
      e.printStackTrace(System.err);
    }//end catch

  }// end main()
  //----------------------------------------------------//

  //This is a convenience method used to separate out the
  // code required to write a lot of XHTML text into the
  // output file.
  static void makeXhtmlText(PrintWriter out){
    
    
    out.println("<?xml version="1.0" "
                       + "encoding="UTF-8"?>");
    out.println(
          "<!DOCTYPE html PUBLIC "-//W3C//DTD "
             + "XHTML 1.0 Transitional//EN" "
             + ""http://www.w3.org/TR/xhtml1/"
             + "DTD/xhtml1-transitional.dtd">");

    out.println(makeElement(false,"html",
      new String[]{"xmlns","http://www.w3.org/1999/xhtml",
                   "xml:lang","en"
                  })//end call to makeElement
    );//end println

    out.println("<head>");
    
    out.println(makeElement(
               true,
               "meta",
               new String[]{"http-equiv","content-type",
                            "content",
                            "image/svg+xml; charset=UTF-8"
                           })//end call to makeElement
    );//end println
  
    out.println("<title>Generated XHTML file</title>");

    out.println("</head>");

    out.println(makeElement(
           false,
           "body",
           new String[]{"style","border:1px solid black;"
                        + "width:220px;"
                        + "height:500px;"
                       })//end call to makeElement
    );//end println
    
  }//end makeXhtmlText
  
  //----------------------------------------------------//
  
  /*
  One of the most frustrating things about using Java
   to create elements in XML, XHTML, or HTML is having
   to deal with the escape characters for the many
   required quotation marks. This method constructs an
   element, which may or may not have attributes. Also,
   the element may or may not be empty.
  The user of this method does not have to deal with the
   required quotation marks surrounding attribute values
   and the corresponding escape characters     
  The first incoming parameter must be true if the
   element is empty and false if the element is not
   empty.
  If the first parameter is true, the element is sealed
   off in the required manner for an empty element. If
   the first parameter is false, the method returns the
   complete start tag for the element but does not
   return a complete element. It is the responsibility
   of the calling method to provide the content and the
   end tag for the element.
  The second parameter to the method must be a String
   that specifies the name of the element.
  The third parameter to the method must be a reference
   to an array object of type String.  This array must 
   contain an even number of elements.  Each pair of 
   elements constitutes the name and the value of an 
   attribute, in the order name, value, name, value, etc.

  If the reference to the array object is null and the
   first parameter is false, the method returns the start
   tag for an element that has no attributes and is not 
   empty.
  If the reference is null and the first parameter is
   true, the method returns a complete empty element with 
   no attributes (which probably doesn't make any sense).
   
  An example of the recommended usage of the method
   follows:
   
  String newElement = SvgGraphics.makeElement(
                  true/false,
                  name,
                  new String[]{"name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value"
                              });//end call to makeElement
   
  */

  static String makeElement(
          boolean empty,String elementName,String[] data){

    //Begin constructing the start tag.
    String element = "<" + elementName + " ";
    
    //Deal with elements that have no attributes.
    if((empty==false) && (data == null)){
      //Return a complete start tag.
      return element + ">";
    }else if((empty==true) && (data == null)){
      //Return a complete empty element.
      return element + "/>";
    }//end if

    for(int cnt=0;cnt<data.length;cnt+=2){

      String name = data[cnt];
      String value = data[cnt+1];
      element += name + "=" + """ + value + "" ";
    }//end for loop
    
    if(empty){
      //Terminate the element appropriately for an
      // empty element. A complete empty element will
      // be returned.
      element += "/>";
    }else{
      //End the start tag for an element that is not
      // empty. In this case, only the start tag will
      // be returned.  The calling program must provide
      // the content for the element as well as the end
      // tag for the element.
      element += ">";
    }//end else
      
    return element;
  }//end makeElement
  //----------------------------------------------------//

}//End class Svg09

 

Listing 11. Program code for Svg10.

/*File Svg10.java
Copyright 2007, R.G.Baldwin

The purpose of this program is to show you how to write a 
simple servlet that will serve a static SVG graphics file
stored on a jakarta-tomcat server running as a localhost 
server under WinXP.

Note that everything reasonable was done to keep this 
servlet as small and simple as practical.

Many thanks go to Marty Hall at 
http://www.apl.jhu.edu/~hall/ 
for helping this author understand:

A.  Where to place static files to cause them to be 
    accessible by a servlet.
B.  How to reference those files within the servlet.
C.  Some other hints regarding good programming practice 
    using Java servlets on a jakarta-tomcat server.

This program can only be tested by deploying the servlet
on a servlet-compatible server and then accessing it 
using an SVG-compatible browser, such as Firefox 1.5.

For this demonstration, the static SVG file is stored in:
C:jakarta-tomcat-5.0.27webappsROOTimages

The servlet class file is stored in:
C:jakarta-tomcat-5.0.27webappsROOTWEB-INFclasses

The servlet is accessed using Firefox at the following 
URL:

http://localhost/servlet/Svg10

The code produced by this servlet was tested and confirmed
to be valid at:

http://validator.w3.org/

The following XML code is produced by this servlet (with 
some line breaks manually entered here for compatibility 
with this narrow publication format):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 
Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html  xml_lang="en" >
<head>
<meta http-equiv="content-type" content="image/svg+xml; 
charset=UTF-8" />
<title>Generated XHTML file</title>
</head>
<body style="border:1px solid black;width:220px;
height:500px;" >
<p>There is an image below here.
<object type="image/svg+xml" width="210" height="430" 
data="/images/Svg10.svg" />
There is an image above here.</p>
</body></html>

Tested using J2SE 5.0, Firefox 1.5.09, and 
jakarta-tomcat-5.0.27 running as a localhost server under
WinXP.
*********************************************************/

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Svg10 extends HttpServlet{

  public void doGet(HttpServletRequest req,
                    HttpServletResponse res)
                      throws ServletException,IOException{
                        
    res.setContentType("image/svg+xml");

    try{
      //Get an output stream.
      PrintWriter out = res.getWriter();
                      
      //Create the beginning text required for the XHTML
      // document.
      makeXhtmlText(out);
      
      //Insert an object element that references a static
      // SVG file in the directory listed in the
      // opening comments to this program. The servlet
      // also causes plain text to be displayed above and
      // below the object element.
      out.println("<p>There is an image below here.");

      out.println(makeElement(
                  true,
                  "object",
                  new String[]{"type","image/svg+xml",
                               "width","210",
                               "height","430",
                               "data","/images/Svg10.svg",
                              })//end call to makeElement
      );//end call to println
      
      out.println("There is an image above here.</p>");

      //Write the final XHTML text and flush the output
      // buffer.
      out.println("</body></html>");
      out.flush();

    }catch(Exception e){
      //Note that no effort was made to provide meaningful
      // information in the event of an exception or
      // error.
      e.printStackTrace(System.err);
    }//end catch

  }// end doGet()
  //----------------------------------------------------//

  //This is a convenience method used to separate out the
  // code required to write a lot of XHTML text into the
  // output file.
  static void makeXhtmlText(PrintWriter out){
    
    
    out.println("<?xml version="1.0" "
                       + "encoding="UTF-8"?>");
    out.println(
          "<!DOCTYPE html PUBLIC "-//W3C//DTD "
             + "XHTML 1.0 Transitional//EN" "
             + ""http://www.w3.org/TR/xhtml1/"
             + "DTD/xhtml1-transitional.dtd">");

    out.println(makeElement(false,"html",
      new String[]{"xmlns","http://www.w3.org/1999/xhtml",
                   "xml:lang","en"
                  })//end call to makeElement
    );//end println

    out.println("<head>");
    
    out.println(makeElement(
               true,
               "meta",
               new String[]{"http-equiv","content-type",
                            "content",
                            "image/svg+xml; charset=UTF-8"
                           })//end call to makeElement
    );//end println
  
    out.println("<title>Generated XHTML file</title>");

    out.println("</head>");

    out.println(makeElement(
           false,
           "body",
           new String[]{"style","border:1px solid black;"
                        + "width:220px;"
                        + "height:500px;"
                       })//end call to makeElement
    );//end println
    
  }//end makeXhtmlText
  //----------------------------------------------------//
  
  /*
  One of the most frustrating things about using Java
   to create elements in XML, XHTML, or HTML is having
   to deal with the escape characters for the many
   required quotation marks. This method constructs an
   element, which may or may not have attributes. Also,
   the element may or may not be empty.
  The user of this method does not have to deal with the
   required quotation marks surrounding attribute values
   and the corresponding escape characters     
  The first incoming parameter must be true if the
   element is empty and false if the element is not
   empty.
  If the first parameter is true, the element is sealed
   off in the required manner for an empty element. If
   the first parameter is false, the method returns the
   complete start tag for the element but does not
   return a complete element. It is the responsibility
   of the calling method to provide the content and the
   end tag for the element.
  The second parameter to the method must be a String
   that specifies the name of the element.
  The third parameter to the method must be a reference
   to an array object of type String.  This array must 
   contain an even number of elements.  Each pair of 
   elements constitutes the name and the value of an 
   attribute, in the order name, value, name, value, etc.

  If the reference to the array object is null and the
   first parameter is false, the method returns the start
   tag for an element that has no attributes and is not 
   empty.
  If the reference is null and the first parameter is
   true, the method returns a complete empty element with 
   no attributes (which probably doesn't make any sense).
   
  An example of the recommended usage of the method
   follows:
   
  String newElement = makeElement(
                  true/false,
                  name,
                  new String[]{"name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value"
                              });//end call to makeElement
   
  */

  static String makeElement(
          boolean empty,String elementName,String[] data){

    //Begin constructing the start tag.
    String element = "<" + elementName + " ";
    
    //Deal with elements that have no attributes.
    if((empty==false) && (data == null)){
      //Return a complete start tag.
      return element + ">";
    }else if((empty==true) && (data == null)){
      //Return a complete empty element.
      return element + "/>";
    }//end if

    for(int cnt=0;cnt<data.length;cnt+=2){

      String name = data[cnt];
      String value = data[cnt+1];
      element += name + "=" + """ + value + "" ";
    }//end for loop
    
    if(empty){
      //Terminate the element appropriately for an
      // empty element. A complete empty element will
      // be returned.
      element += "/>";
    }else{
      //End the start tag for an element that is not
      // empty. In this case, only the start tag will
      // be returned.  The calling program must provide
      // the content for the element as well as the end
      // tag for the element.
      element += ">";
    }//end else
      
    return element;
  }//end makeElement
  //----------------------------------------------------//

}//End class Svg10

 

Listing 12. Program code for Svg11.

/*File Svg11.java
Copyright 2007, R.G.Baldwin

The purpose of this program is to write a servlet that 
will first create a static SVG file and store it on the
server and then serve that file to an SVG-capable web 
client by way of XHTML code that is sent to the client.

The code to accomplish this is somewhat simpler than the
code required to create the SVG graphic code and send it
directly to the client as in-line graphic code.  This is 
because this approach makes better use of JAXP to process 
the DOM tree that represents the graphic image.

This program uses an SVG graphic library that has been
discussed and explained in earlier lessons on this topic.

The program defines a servlet that:

Creates a DOM tree describing a specific graphic image.
Transforms that tree into corresponding SVG XML code.
Writes the SVG code into an output file on the server.

Then the servlet creates the code for a short XHTML 
document that references the SVG file just written and
sends that XHTML code back to the client.

The XHTML code sent to the client is valid according to:

http://validator.w3.org/file-upload.html

This program can only be tested by deploying the servlet
on a servlet-compatible server and then accessing it 
using an SVG-compatible browser, such as Firefox 1.5.

On my system, the SVG file is written into the following
directory:

C:jakarta-tomcat-5.0.27webappsROOTimages

The servlet was tested by copying it into the following 
directory on the Tomcat server:

C:jakarta-tomcat-5.0.27webappsROOTWEB-INFclasses

Then the servlet was accessed using Firefox 1.5.09 at 
the URL given below:

http://localhost/servlet/Svg11

Tested using J2SE 5.0, Firefox 1.5.09, and 
jakarta-tomcat-5.0.27 running as a localhost server under
WinXP.
*********************************************************/

import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

public class Svg11 extends HttpServlet{

  public void doGet(HttpServletRequest req,
                    HttpServletResponse res)
                      throws ServletException,IOException{

    //The following data values will be used to create
    // SVG graphics.
    int ellipseCenterX = 110;
    int ellipseCenterY = 100;
    int ellipseWidth = 100;
    int ellipseHeight = 40;
    int ellipseRotate = 15;//degrees
    
    int circleCenterX = 110;
    int circleCenterY = 100;
    int circleRadius = 30;
    int circleRotate = 15;

    int rectCenterX = 110;
    int rectCenterY = 200;
    int rectWidth = 110;
    int rectHeight = 80;
    int rectRoundX = 26;
    int rectRoundY = 25;
    
    int rotatePolyline = 10;
    
    try{
      //Create a DOM tree that describes a particular
      // graphic image.
      //Begin by creating a Document object and a root
      // node named svg.  All of the graphic content will
      // be contained in the svg element.
      
      //At this point, the program starts using the 
      // SVG graphics library encapsulated in the class
      // named SvgGraphics.
      Document document = SvgGraphics.getDocument();      

      //Create the root node named svg and append it to
      // the document.
      //Set some attributes on the root node that are
      // required for proper rendering.
      Element svg = SvgGraphics.makeNode(
        document,
        null,//parent could be null
        "svg",//node type
        new String[]{"xmlns","http://www.w3.org/2000/svg",
                     "version","1.1",
                     "width","220px",
                     "height","440px",
                     "position","static",
                     "top","0",
                     "left","0"
                    });//end call to makeNode

      //Create a node named defs, which will be the parent
      // for three gradient definitions.  There will be 
      // two linear gradients and one radial gradient.
      // Pass null for the reference to the object for the
      // special case where the node has no attribtes.
      Element defs = SvgGraphics.makeNode(document,
                                          svg,//parent
                                          "defs",
                                          null);

      //Create nodes that define three different gradient
      // coloring schemes.
      //The definitions are identified as gradientA,
      // gradientB, and gradientC.  They will be referred
      // to later to specify the fill colors for an 
      // ellipse, a circle, and a rounded rectangle.

      //Define gradientA, which provides a linear
      // gradient from yellow to red to blue going from
      // left to right.
      Element gradientA = SvgGraphics.makeLinearGradient(
                              document,    //this document
                              defs,        //parent
                              "gradientA");//id
      //Create three stop nodes that identify the colors
      // used to produce the gradient and specify where
      // the colors begin and end, 
      SvgGraphics.makeGradientStop(document,
                                   gradientA,//parent
                                   "2%",     //start here
                                   "yellow");//color
                             
      SvgGraphics.makeGradientStop(document,
                                   gradientA,
                                   "50%",
                                   "red");
                             
      SvgGraphics.makeGradientStop(document,
                                   gradientA,
                                   "98%",
                                   "blue");
      
      //Define gradientB, which provides a linear
      // gradient having two stops from green to blue
      // going from left to right.
      Element gradientB =SvgGraphics.makeLinearGradient(
                             document,    //this document
                             defs,        //parent
                             "gradientB");//id
                   
      SvgGraphics.makeGradientStop(document,
                                   gradientB,//parent
                                   "0%",     //start here
                                   "green"); //color
                             
      SvgGraphics.makeGradientStop(document,
                                   gradientB,
                                   "100%",
                                   "blue");
                                     
      //Define gradientC, which provides a radial
      // gradient from yellow to red to blue going from
      // the center to the outer edge.
      Element gradientC = 
                 SvgGraphics.makeRadialGradient(
                   document,        //this document
                   defs,            //parent
                   "gradientC",     //ID
                   "userSpaceOnUse",
                   rectCenterX,     //cx
                   rectCenterY,     //cy
                   rectWidth/2);    //r
                   
      SvgGraphics.makeGradientStop(document,
                                   gradientC,
                                   "0%",
                                   "yellow");
                             
      SvgGraphics.makeGradientStop(document,
                                   gradientC,
                                   "50%",
                                   "red");
                             
      SvgGraphics.makeGradientStop(document,
                                   gradientC,
                                   "100%",
                                   "blue");
                                   
      //Create a node named g, which will be the parent
      // for an ellipse,a circle, a rectangle, a line,
      // a polyline, and a polygon. Pass null for the
      // reference to the object for the special case
      // where the node has no attribtes.
      Element g = SvgGraphics.makeNode(document,
                                       svg,//parent
                                       "g",
                                       null);

      //Create an ellipse with a blue border that is two
      // pixels wide. Fill it with the yellow-red-blue
      // gradient defined by gradientA.
      Element theEllipse = SvgGraphics.makeEllipse(
                             document,
                             g,//Owner
                             ellipseCenterX,
                             ellipseCenterY,
                             ellipseWidth,
                             ellipseHeight);
      //Set the appearance of the ellipse.
      theEllipse.setAttribute("fill","url(#gradientA)");
      theEllipse.setAttribute("stroke","blue");
      theEllipse.setAttribute("stroke-width","2");
      
      //Rotate the ellipse by 15-degrees clockwise about
      // its center.
      theEllipse.setAttribute("transform",
                  "translate(" + ellipseCenterX + "," 
                  + ellipseCenterY + ") "
                  + "rotate(" + ellipseRotate + ") "
                  + "translate(" + (-ellipseCenterX) + ","
                  + (-ellipseCenterY) + ") ");

      //Position a circle so that it appears to be inside
      // the ellipse.  Fill it with the green-blue
      // gradient defined by gradientB.
      Element theCircle = SvgGraphics.makeCircle(
                            document,
                            g,//Owner
                            circleCenterX,
                            circleCenterY,
                            circleRadius);
                            
      //Set the appearance of the circle and rotate it by
      // 15-degrees clockwise about its center.
      theCircle.setAttribute("fill","url(#gradientB)");
      theCircle.setAttribute("transform",
                   "translate(" + circleCenterX + "," 
                   + circleCenterY + ") "
                   + "rotate(" + circleRotate + ") "
                   + "translate(" + (-circleCenterX) + ","
                   + (-circleCenterY) + ") ");

      //Make a rounded rectangle and fill it with
      // gradientC
      Element theRect = SvgGraphics.makeRect(
                            document,
                            g,//Owner
                            rectCenterX - rectWidth/2,//x
                            rectCenterY - rectHeight/2,//y
                            rectWidth,
                            rectHeight);

      theRect.setAttribute("fill","url(#gradientC)");

      //Round the corners.
      theRect.setAttribute("rx",""+ rectRoundX);
      theRect.setAttribute("ry",""+ rectRoundY);

      //Draw a polyline with four points.
      int[] polylinePoints = 
                         {10,235,210,235,110,275,110,225};
      Element polyline = SvgGraphics.makePolyline(
                                          document,
                                          g,//owner
                                          polylinePoints);
      
      //Rotate the polyline by 10 degrees around the first
      // point.
      polyline.setAttribute("transform",
                    "translate(" + polylinePoints[0] + ","
                    + polylinePoints[1] + ")" 
                    + "rotate(" + rotatePolyline + ")" 
                    + "translate(" + (-polylinePoints[0]) 
                    + "," + (-polylinePoints[1]) + ")");
      
      //Draw a polygon with four points. Give it a red
      // border and fill it with green.
      int[] polygonPoints = 
                         {10,335,210,335,110,375,110,325};
      Element polygon = SvgGraphics.makePolygon(
                                           document,
                                           g,//parent
                                           polygonPoints);
      polygon.setAttribute("fill","green");
      polygon.setAttribute("stroke","red");
      polygon.setAttribute("stroke-width","3");
      
      //Draw a green line 12 pixels wide.  Make the line
      // 60% opaque, or 40% transparent, whichever you
      // prefer.
      Element line = SvgGraphics.makeLine(document,
                                          g,   //owner
                                          0,   //x1
                                          0,   //y1
                                          220, //x2
                                          440);//y2
      line.setAttribute("stroke","green");
      line.setAttribute("stroke-width","12");
      line.setAttribute("stroke-opacity","0.6");


      //Now transform the DOM tree into SVG XML code and
      // write that code into an SVG file on the server.
      SvgGraphics.transformTheDom(document,
        getServletContext().getRealPath("/") + "images" 
                          + File.separator + "Svg11.svg");
      
      //Get an output stream for the XHTML text that will
      // be sent directly from the servlet to the browser.
      PrintWriter out = res.getWriter();

      res.setContentType("image/svg+xml");
                      
      //Create the beginning text required for the XHTML
      // document.
      makeXhtmlText(out);
      
      //Insert an object element that references a static
      // SVG file in the directory listed in the
      // opening comments to this program. The servlet
      // also causes plain text to be displayed above and
      // below the object element.
      out.println("<p>There is an image below here.");

      out.println(SvgGraphics.makeElement(
                  true,
                  "object",
                  new String[]{"type","image/svg+xml",
                               "width","210",
                               "height","430",
                               "data","/images/Svg11.svg",
                              })//end call to makeElement
      );//end call to println
      
      out.println("There is an image above here.</p>");

      //Write the final XHTML text and flush the output
      // buffer.
      out.println("</body></html>");
      out.flush();

    }catch(Exception e){
      //Note that no effort was made to provide meaningful
      // information in the event of an exception or
      // error.
      e.printStackTrace(System.err);
    }//end catch

  }// end doGet()
  //----------------------------------------------------//

  //This is a convenience method used to separate out the
  // code required to write a lot of XHTML text into the
  // output file.
  static void makeXhtmlText(PrintWriter out){
    
    
    out.println("<?xml version="1.0" "
                       + "encoding="UTF-8"?>");
    out.println(
          "<!DOCTYPE html PUBLIC "-//W3C//DTD "
             + "XHTML 1.0 Transitional//EN" "
             + ""http://www.w3.org/TR/xhtml1/"
             + "DTD/xhtml1-transitional.dtd">");

    out.println(SvgGraphics.makeElement(false,"html",
      new String[]{"xmlns","http://www.w3.org/1999/xhtml",
                   "xml:lang","en"
                  })//end call to makeElement
    );//end println

    out.println("<head>");
    
    out.println(SvgGraphics.makeElement(
               true,
               "meta",
               new String[]{"http-equiv","content-type",
                            "content",
                            "image/svg+xml; charset=UTF-8"
                           })//end call to makeElement
    );//end println
  
    out.println("<title>Generated XHTML file</title>");

    out.println("</head>");

    out.println(SvgGraphics.makeElement(
           false,
           "body",
           new String[]{"style","border:1px solid black;"
                        + "width:220px;"
                        + "height:500px;"
                       })//end call to makeElement
    );//end println
    
  }//end makeXhtmlText
  
  //----------------------------------------------------//


}//End class Svg11
//======================================================//

//This is a proof-of-concept graphics class that
// provides method calls for the creation of the following
// DOM tree nodes:
//  A general node of any type
//  A linear gradient element.
//  A radial gradient element.
//  An ellipse.
//  A circle.
//  A rectangle.
//  A line.
//  A polyline.
//  A polygon.

//Each method receives a reference to the overall document
// along with a reference to the parent for the new node.
//When the method returns, the new node has been appended
// to the parent node.
class SvgGraphics{
  //----------------------------------------------------//

  //This method creates a linear gradient node to which
  // stop elements must be appended.
  static Element makeLinearGradient(Document document,
                                    Element parent,
                                    String id){
    Element gradient = 
        (Element)document.createElement("linearGradient");
    parent.appendChild(gradient);
    gradient.setAttribute("id",id);
    return gradient;
  }//End makeLinearGradient
  //----------------------------------------------------//
  
  //This method creates a radial gradient node to which
  // stop elements must be appended. Note that numeric
  // attributes are set as type String.
  static Element makeRadialGradient(Document document,
                                    Element parent,
                                    String id,
                                    String gradientUnits,
                                    int cx,
                                    int cy,
                                    int r){
    Element gradient = 
        (Element)document.createElement("radialGradient");
    parent.appendChild(gradient);
    gradient.setAttribute("id",id);
    gradient.setAttribute("gradientUnits",gradientUnits);
    gradient.setAttribute("cx",""+cx);
    gradient.setAttribute("cy",""+cy);
    gradient.setAttribute("r",""+r);
    return gradient;
  }//End makeRadialGradient
  //----------------------------------------------------//

  //This method creates a gradient stop node to be
  // appended to a linear gradient node or a radial
  // gradient node.                                      
  static Element makeGradientStop(Document document,
                                  Element parent,
                                  String location,
                                  String color){
    Element stopElement = 
                  (Element)document.createElement("stop");
    parent.appendChild(stopElement);
    stopElement.setAttribute("offset",location);
    stopElement.setAttribute("stop-color",color);
    return stopElement;
  }//End makeGradientStop
  //----------------------------------------------------//
  
  //This method returns a reference to an ellipse. The
  // xCoor and yCoor parameters specify the center of the
  // ellipse.  The xRadius and yRadius parameters specify
  // the width and height of the  ellipse respectively
  // while it is in the horizontal plane before being
  // rotated.  Numeric attributes are set at type String.
  static Element makeEllipse(Document document,
                             Element parent,
                             int xCoor,
                             int yCoor,
                             int xRadius,
                             int yRadius){
    Element ellipse  = 
               (Element)document.createElement("ellipse");
    parent.appendChild(ellipse);
    ellipse.setAttribute("cx",""+xCoor);
    ellipse.setAttribute("cy",""+yCoor);
    ellipse.setAttribute("rx",""+xRadius);
    ellipse.setAttribute("ry",""+yRadius);
    return ellipse;
  }//end makeEllipse
  //----------------------------------------------------//

  //This method returns a reference to a circle. The
  // xCoor and yCoor parameters specify the center of the
  // circle.  The radius parameter specifies the radus of
  // the circle.  Numeric attributes are set as type
  // String.
  static Element makeCircle(Document document,
                            Element parent,
                            int xCoor,
                            int yCoor,
                            int radius){
    Element circle  = 
                (Element)document.createElement("circle");
    parent.appendChild(circle);
    circle.setAttribute("cx",""+xCoor);
    circle.setAttribute("cy",""+yCoor);
    circle.setAttribute("r",""+radius);
    return circle;
  }//end makeCircle
  //----------------------------------------------------//
  
  //This method returns a reference to a rectangle. The
  // xCoor and yCoor parameters specify the location of
  // the upper left corner.  The width and height
  // parameters specify the width and the height while
  // the rectangle is in the horizontal plane before
  // being rotated.  Numeric attributes are set as type
  // String.
  static Element makeRect(Document document,
                          Element parent,
                          int xCoor,
                          int yCoor,
                          int width,
                          int height){
    Element rect  = 
                  (Element)document.createElement("rect");
    parent.appendChild(rect);
    rect.setAttribute("x",""+xCoor);
    rect.setAttribute("y",""+yCoor);
    rect.setAttribute("width",""+width);
    rect.setAttribute("height",""+height);
    return rect;
  }//end makeRect
  
  //----------------------------------------------------//
  
  //This method returns a reference to a line. x1 and y1
  // specify the starting point of the line before it is
  // rotated. x2 and y2 specify the end point.  By
  // default, the stroke is set to black one pixel wide.
  // This can be overridden to speciy other colors and
  // other widths if you need to do so.
  static Element makeLine(Document document,
                          Element parent,
                          int x1,
                          int y1,
                          int x2,
                          int y2){
    Element line  = 
                  (Element)document.createElement("line");
    parent.appendChild(line);
    line.setAttribute("x1",""+x1);
    line.setAttribute("y1",""+y1);
    line.setAttribute("x2",""+x2);
    line.setAttribute("y2",""+y2);
    line.setAttribute("stroke","black");
    line.setAttribute("stroke-width","1");
    return line;
  }//end makeLine
  //----------------------------------------------------//

  //This method returns a reference to a polyline. The
  // array of type int[] must contain an even number of
  // values for things to work correctly.
  //The values are extracted from the array and treated
  // as coordinate values x1,y1, x2,y2, x3,y3 ... etc.
  // By default, the stroke is set to black one pixel
  // wide with no fill.  This can be overridden to other
  // colors and other widths if you need to do so.
  static Element makePolyline(Document document,
                              Element parent,
                              int[] points){
    Element polyline  = 
              (Element)document.createElement("polyline");
    parent.appendChild(polyline);

    String dataPoints = "";
    for(int cnt=0;cnt<points.length;cnt++){
      dataPoints += "" + points[cnt] + ",";
    }//end for loop
    
    polyline.setAttribute("points",dataPoints);
    polyline.setAttribute("stroke","black");
    polyline.setAttribute("stroke-width","1");
    polyline.setAttribute("fill","none");
    return polyline;
  }//end makePolyline
  //----------------------------------------------------//
  
  //This method returns a reference to a polygon. The
  // array of type int[] must contain an even number of
  // values for things to work correctly.
  //The values are extracted from the array and treated
  // as coordinate values x1,y1, x2,y2, x3,y3 ... etc.
  // By default, the stroke is set to black, one pixel
  // wide with no fill.  This can be overridden to other
  // colors and other widths if you need to do so.
  //The major difference between a polygon and a polyline
  // is that a polyline leaves the last point dangling.
  // However, a polygon automatically draws a line from
  // the last point back to the first point to close
  // the polygon.
  static Element makePolygon(Document document,
                           Element parent,
                           int[] points){
    Element polygon  = 
               (Element)document.createElement("polygon");
    parent.appendChild(polygon);

    String dataPoints = "";
    for(int cnt=0;cnt<points.length;cnt++){
      dataPoints += "" + points[cnt] + ",";
    }//end for loop
    
    polygon.setAttribute("points",dataPoints);
    polygon.setAttribute("stroke","black");
    polygon.setAttribute("stroke-width","1");
    polygon.setAttribute("fill","none");
    return polygon;
  }//end makePolygon
  
  //----------------------------------------------------//
  
  /*
  One of the most frustrating things about using Java
   to create elements in XML, XHTML, or HTML is having
   to deal with the escape characters for the many
   required quotation marks. This method constructs an
   element, which may or may not have attributes. Also,
   the element may or may not be empty.
  The user of this method does not have to deal with the
   required quotation marks surrounding attribute values
   and the corresponding escape characters     
  The first incoming parameter must be true if the
   element is empty and false if the element is not
   empty.
  If the first parameter is true, the element is sealed
   off in the required manner for an empty element. If
   the first parameter is false, the method returns the
   complete start tag for the element but does not
   return a complete element. It is the responsibility
   of the calling method to provide the content and the
   end tag for the element.
  The second parameter to the method must be a String
   that specifies the name of the element.
  The third parameter to the method must be a reference
   to an array object of type String.  This array must 
   contain an even number of elements.  Each pair of 
   elements constitutes the name and the value of an 
   attribute, in the order name, value, name, value, etc.

  If the reference to the array object is null and the
   first parameter is false, the method returns the start
   tag for an element that has no attributes and is not 
   empty.
  If the reference is null and the first parameter is
   true, the method returns a complete empty element with 
   no attributes (which probably doesn't make any sense).
   
  An example of the recommended usage of the method
   follows:
   
  String newElement = SvgGraphics.makeElement(
                  true/false,
                  name,
                  new String[]{"name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value",
                               "name","value"
                              });//end call to makeElement
   
  */
  
  static String makeElement(
          boolean empty,String elementName,String[] data){

    //Begin constructing the start tag.
    String element = "<" + elementName + " ";
    
    //Deal with elements that have no attributes.
    if((empty==false) && (data == null)){
      //Return a complete start tag.
      return element + ">";
    }else if((empty==true) && (data == null)){
      //Return a complete empty element.
      return element + "/>";
    }//end if

    for(int cnt=0;cnt<data.length;cnt+=2){

      String name = data[cnt];
      String value = data[cnt+1];
      element += name + "=" + """ + value + "" ";
    }//end for loop
    
    if(empty){
      //Terminate the element appropriately for an
      // empty element. A complete empty element will
      // be returned.
      element += "/>";
    }else{
      //End the start tag for an element that is not
      // empty. In this case, only the start tag will
      // be returned.  The calling program must provide
      // the content for the element as well as the end
      // tag for the element.
      element += ">";
    }//end else
      
  return element;
  }//end makeElement
  //----------------------------------------------------//
  
  /*
  The purpose of this method is to create a general node
   having any name, and any number of attributes with any 
   attribute names and any String values for the 
   attributes, or no attributes at all.
   
  The first parameter is a reference to the document to
   which the new node belongs.
  
  The second parameter is a reference to the parent node
   to which this node is to be appended so as to become a
   child of that node. If this parameter is null, the new
   node is appended to the document.  Otherwise, it is
   appended to the specified parent node.
   
  The third parameter is a String that specifies the type
   of node.
  
  The fourth parameter to the method must be a reference
   to an array object of type String.  This array must 
   contain an even number of elements.  Each pair of 
   elements constitutes the name and the value of an 
   attribute, in the order name, value, name, value, etc.
  
  An example of the recommended usage of the method
   follows:
  Element abc = SvgGraphics.makeNode(
                     document,
                     def,//parent could be null
                     "ghi",//node type
                     new String[]{"name","value",
                                  "name","value",
                                  "name","value",
                                  "name","value",
                                  "name","value",
                                  "name","value",
                                  "name","value",
                                  "name","value",
                                  "name","value"
                                 });//end call to makeNode
  */
  static Element makeNode(Document document,
                                Element parent,
                                String nodeType,
                                String[] data){
  
    Element element = 
                (Element)document.createElement(nodeType);
    
    if(parent == null){
      //For the special case of parent equal to null,
      // append the new node to the document.
      document.appendChild(element);
    }else{
      //Otherwise, append the new node to the specified
      // parent.
      parent.appendChild(element);
    }//end else
  
    //Deal with elements that have no attributes.
    if(data == null){
      return element;
    }//end if
    
    for(int cnt=0;cnt<data.length;cnt+=2){
      String name = data[cnt];
      String value = data[cnt+1];
      element.setAttribute(name,value);
    }//end for loop
    
    return element;
  }//end makeNode
  //----------------------------------------------------//
  
  //This is a utility method that is used to execute code
  // that is the same regardless of the graphic image
  // being produced.
  static Document getDocument(){
    Document document = null;
    try{
      DocumentBuilderFactory factory = 
                     DocumentBuilderFactory.newInstance();

      DocumentBuilder builder = 
                             factory.newDocumentBuilder();
      document = builder.newDocument();

    }catch(Exception e){
      e.printStackTrace(System.err);
      System.exit(0);
    }//end catch
    return document;
  }//end getDocument
  //----------------------------------------------------//
  
  //This is a utility method that is used to execute code
  // that is the same regardless of the graphic image
  // being produced.  This method transforms the DOM into
  // raw XML code and writes that code into the output.
  static void transformTheDom(Document document,
                              String filename){
    try{
      //Get a TransformerFactory object.
      TransformerFactory xformFactory =
                         TransformerFactory.newInstance();
           
      //Get an XSL Transformer object.
      Transformer transformer = 
                            xformFactory.newTransformer();
    
      //Get a DOMSource object that represents the
      // Document object
      DOMSource source = new DOMSource(document);

      //Get an output stream for the output file.
      PrintWriter outStream = new PrintWriter(filename);

      //Get a StreamResult object that points to the
      // output file.  Then transform the DOM sending XML
      // code to to the file
      StreamResult fileResult = 
                              new StreamResult(outStream);
      transformer.transform(source,fileResult);
    }//end try block

    catch(Exception e){
      e.printStackTrace(System.err);
    }//end catch
  }//end transformTheDom
  //----------------------------------------------------//
}//end class SvgGraphics

 


Copyright

Copyright 2007, Richard G. Baldwin.  Reproduction in whole or in part in any
form or medium without express written permission from Richard Baldwin is
prohibited.

About the author

Richard Baldwin is a
college professor (at Austin Community College in Austin, TX) and private
consultant whose primary focus is a combination of Java, C#, and XML. In
addition to the many platform and/or language independent benefits of Java and
C# applications, he believes that a combination of Java, C#, and XML will become
the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he
frequently provides onsite training at the high-tech companies located in and
around Austin, Texas.  He is the author of Baldwin’s Programming
Tutorials, which have gained a
worldwide following among experienced and aspiring programmers. He has also
published articles in JavaPro magazine.

In addition to his programming expertise, Richard has many years of
practical experience in Digital Signal Processing (DSP).  His first job after he
earned his Bachelor’s degree was doing DSP in the Seismic Research Department of
Texas Instruments.  (TI is still a world leader in DSP.)  In the following
years, he applied his programming and DSP expertise to other interesting areas
including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has
many years of experience in the application of computer technology to real-world
problems.

Baldwin@DickBaldwin.com

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories