December 22, 2014
Hot Topics:

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

  • June 19, 2007
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

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 xmlns="http://www.w3.org/1999/xhtml" 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 xmlns="http://www.w3.org/1999/xhtml" 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 xmlns="http://www.w3.org/1999/xhtml" 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






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel