View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.jelly.tags.xml;
17  
18  import org.apache.commons.jelly.JellyTagException;
19  import org.apache.commons.jelly.TagSupport;
20  import org.apache.commons.jelly.XMLOutput;
21  import org.xml.sax.Attributes;
22  import org.xml.sax.SAXException;
23  import org.xml.sax.helpers.AttributesImpl;
24  
25  /*** A tag to produce an XML element which can contain other attributes
26    * or elements like the <code>&lt;xsl:element&gt;</code> tag.
27    *
28    * @author James Strachan
29    * @version $Revision: 1.5 $
30    */
31  public class ElementTag extends TagSupport {
32  
33      /*** The namespace URI */
34      private String namespace;
35  
36      /*** The qualified name */
37      private String name;
38  
39      /*** The XML Attributes */
40      private AttributesImpl attributes = new AttributesImpl();
41  
42      /*** flag set if attributes are output */
43      private boolean outputAttributes;
44  
45      public ElementTag() {
46      }
47  
48      /***
49       * Sets the attribute of the given name to the specified value.
50       *
51       * @param name of the attribute
52       * @param value of the attribute
53       * @throws JellyException if the start element has already been output.
54       *   Attributes must be set on the outer element before any content
55       *   (child elements or text) is output
56       */
57      public void setAttributeValue( String name, String value ) throws JellyTagException {
58          if (outputAttributes) {
59              throw new JellyTagException(
60                  "Cannot set the value of attribute: "
61                  + name + " as we have already output the startElement() SAX event"
62              );
63          }
64  
65          // ### we'll assume that all attributes are in no namespace!
66          // ### this is severely limiting!
67          // ### we should be namespace aware
68          int index = attributes.getIndex("", name);
69          if (index >= 0) {
70              attributes.removeAttribute(index);
71          }
72          // treat null values as no attribute
73          if (value != null) {
74              attributes.addAttribute("", name, name, "CDATA", value);
75          }
76      }
77  
78      // Tag interface
79      //-------------------------------------------------------------------------
80      public void doTag(XMLOutput output) throws JellyTagException {
81          int idx = name.indexOf(':');
82          final String localName = (idx >= 0)
83              ? name.substring(idx + 1)
84              : name;
85  
86          outputAttributes = false;
87  
88          XMLOutput newOutput = new XMLOutput(output) {
89  
90              // add an initialize hook to the core content-generating methods
91  
92              public void startElement(
93                  String uri,
94                  String localName,
95                  String qName,
96                  Attributes atts)
97                  throws SAXException {
98                  initialize();
99                  super.startElement(uri, localName, qName, atts);
100             }
101 
102             public void endElement(String uri, String localName, String qName)
103                 throws SAXException {
104                 initialize();
105                 super.endElement(uri, localName, qName);
106             }
107 
108             public void characters(char ch[], int start, int length) throws SAXException {
109                 initialize();
110                 super.characters(ch, start, length);
111             }
112 
113             public void ignorableWhitespace(char ch[], int start, int length)
114                 throws SAXException {
115                 initialize();
116                 super.ignorableWhitespace(ch, start, length);
117             }
118             public void processingInstruction(String target, String data)
119                 throws SAXException {
120                 initialize();
121                 super.processingInstruction(target, data);
122             }
123 
124             /***
125              * Ensure that the outer start element is generated
126              * before any content is output
127              */
128             protected void initialize() throws SAXException {
129                 if (!outputAttributes) {
130                     super.startElement(namespace, localName, name, attributes);
131                     outputAttributes = true;
132                 }
133             }
134         };
135 
136         invokeBody(newOutput);
137 
138         try {
139             if (!outputAttributes) {
140                 output.startElement(namespace, localName, name, attributes);
141                 outputAttributes = true;
142             }
143 
144             output.endElement(namespace, localName, name);
145             attributes.clear();
146         } catch (SAXException e) {
147             throw new JellyTagException(e);
148         }
149     }
150 
151     // Properties
152     //-------------------------------------------------------------------------
153 
154     /***
155      * @return the qualified name of the element
156      */
157     public String getName() {
158         return name;
159     }
160 
161     /***
162      * Sets the qualified name of the element
163      */
164     public void setName(String name) {
165         this.name = name;
166     }
167 
168     /***
169      * @return the namespace URI of the element
170      */
171     public String getURI() {
172         return namespace;
173     }
174 
175     /***
176      * Sets the namespace URI of the element
177      */
178     public void setURI(String namespace) {
179         this.namespace = namespace;
180     }
181 }