Makefile.am: New file.
* external/w3c_dom/Makefile.am: New file. * external/w3c_dom/Makefile.in: New file. * external/sax/Makefile.am: New file. * external/sax/Makefile.in: New file. * external/Makefile.in: New file. * external/Makefile.am: New file. * external/README: New file from Classpath. * configure, aclocal.m4, Makefile.in: Rebuilt. * configure.ac (AC_CONFIG_FILES): Create new Makefiles. * Makefile.am (SUBDIRS): Added external. (toolexeclib_LTLIBRARIES): Removed lib-org-xml-sax.la, lib-org-w3c-dom.la, lib-org-ietf-gss.la. (BOOTCLASSPATH): New variable. (AM_GCJFLAGS): Use it. (gnu_xml_source_files): New variable. (libgcj_la_SOURCES): Use it. (libgcj_la_LDADD): Include new convenience libraries. (lib_org_ietf_jgss_la_SOURCES): Removed. (lib_org_ietf_jgss_la_DEPENDENCIES): Likewise. (lib_org_ietf_jgss_la_LIBADD): Likewise. (lib_org_w3c_dom_la_SOURCES): Removed. (lib_org_w3c_dom_la_DEPENDENCIES): Likewise. (lib_org_w3c_dom_la_LIBADD): Likewise. (lib_org_xml_sax_la_SOURCES): Removed. (lib_org_xml_sax_la_DEPENDENCIES): Likewise. (lib_org_xml_sax_la_LIBADD): Likewise. (all_java_source_files): Updated. (property_files): Likewise. (libgcj-@gcc_version@.jar): Include classes from external/. (javax_source_files): Updated. (ordinary_java_source_files): Updated. * javax/xml/XMLConstants.java, javax/xml/datatype/DatatypeConfigurationException.java, javax/xml/datatype/DatatypeConstants.java, javax/xml/datatype/DatatypeFactory.java, javax/xml/datatype/Duration.java, javax/xml/datatype/XMLGregorianCalendar.java, javax/xml/datatype/package.html, javax/xml/namespace/NamespaceContext.java, javax/xml/namespace/QName.java, javax/xml/namespace/package.html, javax/xml/parsers/DocumentBuilder.java, javax/xml/parsers/DocumentBuilderFactory.java, javax/xml/parsers/FactoryConfigurationError.java, javax/xml/parsers/ParserConfigurationException.java, javax/xml/parsers/SAXParser.java, javax/xml/parsers/SAXParserFactory.java, javax/xml/parsers/package.html, javax/xml/transform/ErrorListener.java, javax/xml/transform/OutputKeys.java, javax/xml/transform/Result.java, javax/xml/transform/Source.java, javax/xml/transform/SourceLocator.java, javax/xml/transform/Templates.java, javax/xml/transform/Transformer.java, javax/xml/transform/TransformerConfigurationException.java, javax/xml/transform/TransformerException.java, javax/xml/transform/TransformerFactory.java, javax/xml/transform/TransformerFactoryConfigurationError.java, javax/xml/transform/URIResolver.java, javax/xml/transform/package.html, javax/xml/transform/dom/DOMLocator.java, javax/xml/transform/dom/DOMResult.java, javax/xml/transform/dom/DOMSource.java, javax/xml/transform/dom/package.html, javax/xml/transform/sax/SAXResult.java, javax/xml/transform/sax/SAXSource.java, javax/xml/transform/sax/SAXTransformerFactory.java, javax/xml/transform/sax/TemplatesHandler.java, javax/xml/transform/sax/TransformerHandler.java, javax/xml/transform/sax/package.html, javax/xml/transform/stream/StreamResult.java, javax/xml/transform/stream/StreamSource.java, javax/xml/transform/stream/package.html, javax/xml/validation/Schema.java, javax/xml/validation/SchemaFactory.java, javax/xml/validation/TypeInfoProvider.java, javax/xml/validation/Validator.java, javax/xml/validation/ValidatorHandler.java, javax/xml/validation/package.html, javax/xml/xpath/XPath.java, javax/xml/xpath/XPathConstants.java, javax/xml/xpath/XPathException.java, javax/xml/xpath/XPathExpression.java, javax/xml/xpath/XPathExpressionException.java, javax/xml/xpath/XPathFactory.java, javax/xml/xpath/XPathFactoryConfigurationException.java, javax/xml/xpath/XPathFunction.java, javax/xml/xpath/XPathFunctionException.java, javax/xml/xpath/XPathFunctionResolver.java, javax/xml/xpath/XPathVariableResolver.java, javax/xml/xpath/package.html: New files, from GNU JAXP. * org/w3c/dom/Attr.java, org/w3c/dom/CDATASection.java, org/w3c/dom/CharacterData.java, org/w3c/dom/Comment.java, org/w3c/dom/DOMException.java, org/w3c/dom/DOMImplementation.java, org/w3c/dom/Document.java, org/w3c/dom/DocumentFragment.java, org/w3c/dom/DocumentType.java, org/w3c/dom/Element.java, org/w3c/dom/Entity.java, org/w3c/dom/EntityReference.java, org/w3c/dom/NamedNodeMap.java, org/w3c/dom/Node.java, org/w3c/dom/NodeList.java, org/w3c/dom/Notation.java, org/w3c/dom/ProcessingInstruction.java, org/w3c/dom/Text.java, org/w3c/dom/ranges/DocumentRange.java, org/w3c/dom/ranges/Range.java, org/w3c/dom/ranges/RangeException.java, org/w3c/dom/traversal/DocumentTraversal.java, org/w3c/dom/traversal/NodeFilter.java, org/w3c/dom/traversal/NodeIterator.java, org/w3c/dom/traversal/TreeWalker.java, org/xml/sax/AttributeList.java, org/xml/sax/Attributes.java, org/xml/sax/ContentHandler.java, org/xml/sax/DTDHandler.java, org/xml/sax/DocumentHandler.java, org/xml/sax/EntityResolver.java, org/xml/sax/ErrorHandler.java, org/xml/sax/HandlerBase.java, org/xml/sax/InputSource.java, org/xml/sax/Locator.java, org/xml/sax/Parser.java, org/xml/sax/SAXException.java, org/xml/sax/SAXNotRecognizedException.java, org/xml/sax/SAXNotSupportedException.java, org/xml/sax/SAXParseException.java, org/xml/sax/XMLFilter.java, org/xml/sax/XMLReader.java, org/xml/sax/package.html, org/xml/sax/ext/DeclHandler.java, org/xml/sax/ext/LexicalHandler.java, org/xml/sax/ext/package.html, org/xml/sax/helpers/AttributeListImpl.java, org/xml/sax/helpers/AttributesImpl.java, org/xml/sax/helpers/DefaultHandler.java, org/xml/sax/helpers/LocatorImpl.java, org/xml/sax/helpers/NamespaceSupport.java, org/xml/sax/helpers/NewInstance.java, org/xml/sax/helpers/ParserAdapter.java, org/xml/sax/helpers/ParserFactory.java, org/xml/sax/helpers/XMLFilterImpl.java, org/xml/sax/helpers/XMLReaderAdapter.java, org/xml/sax/helpers/XMLReaderFactory.java, org/xml/sax/helpers/package.html: Moved to external/. * external/sax/README, external/sax/org/xml/sax/AttributeList.java, external/sax/org/xml/sax/Attributes.java, external/sax/org/xml/sax/ContentHandler.java, external/sax/org/xml/sax/DTDHandler.java, external/sax/org/xml/sax/DocumentHandler.java, external/sax/org/xml/sax/EntityResolver.java, external/sax/org/xml/sax/ErrorHandler.java, external/sax/org/xml/sax/HandlerBase.java, external/sax/org/xml/sax/InputSource.java, external/sax/org/xml/sax/Locator.java, external/sax/org/xml/sax/Parser.java, external/sax/org/xml/sax/SAXException.java, external/sax/org/xml/sax/SAXNotRecognizedException.java, external/sax/org/xml/sax/SAXNotSupportedException.java, external/sax/org/xml/sax/SAXParseException.java, external/sax/org/xml/sax/XMLFilter.java, external/sax/org/xml/sax/XMLReader.java, external/sax/org/xml/sax/package.html, external/sax/org/xml/sax/ext/Attributes2.java, external/sax/org/xml/sax/ext/Attributes2Impl.java, external/sax/org/xml/sax/ext/DeclHandler.java, external/sax/org/xml/sax/ext/DefaultHandler2.java, external/sax/org/xml/sax/ext/EntityResolver2.java, external/sax/org/xml/sax/ext/LexicalHandler.java, external/sax/org/xml/sax/ext/Locator2.java, external/sax/org/xml/sax/ext/Locator2Impl.java, external/sax/org/xml/sax/ext/package.html, external/sax/org/xml/sax/helpers/AttributeListImpl.java, external/sax/org/xml/sax/helpers/AttributesImpl.java, external/sax/org/xml/sax/helpers/DefaultHandler.java, external/sax/org/xml/sax/helpers/LocatorImpl.java, external/sax/org/xml/sax/helpers/NamespaceSupport.java, external/sax/org/xml/sax/helpers/NewInstance.java, external/sax/org/xml/sax/helpers/ParserAdapter.java, external/sax/org/xml/sax/helpers/ParserFactory.java, external/sax/org/xml/sax/helpers/XMLFilterImpl.java, external/sax/org/xml/sax/helpers/XMLReaderAdapter.java, external/sax/org/xml/sax/helpers/XMLReaderFactory.java, external/sax/org/xml/sax/helpers/package.html, external/w3c_dom/COPYRIGHT.html, external/w3c_dom/README, external/w3c_dom/org/w3c/dom/Attr.java, external/w3c_dom/org/w3c/dom/CDATASection.java, external/w3c_dom/org/w3c/dom/CharacterData.java, external/w3c_dom/org/w3c/dom/Comment.java, external/w3c_dom/org/w3c/dom/DOMConfiguration.java, external/w3c_dom/org/w3c/dom/DOMError.java, external/w3c_dom/org/w3c/dom/DOMErrorHandler.java, external/w3c_dom/org/w3c/dom/DOMException.java, external/w3c_dom/org/w3c/dom/DOMImplementation.java, external/w3c_dom/org/w3c/dom/DOMImplementationList.java, external/w3c_dom/org/w3c/dom/DOMImplementationSource.java, external/w3c_dom/org/w3c/dom/DOMLocator.java, external/w3c_dom/org/w3c/dom/DOMStringList.java, external/w3c_dom/org/w3c/dom/Document.java, external/w3c_dom/org/w3c/dom/DocumentFragment.java, external/w3c_dom/org/w3c/dom/DocumentType.java, external/w3c_dom/org/w3c/dom/Element.java, external/w3c_dom/org/w3c/dom/Entity.java, external/w3c_dom/org/w3c/dom/EntityReference.java, external/w3c_dom/org/w3c/dom/NameList.java, external/w3c_dom/org/w3c/dom/NamedNodeMap.java, external/w3c_dom/org/w3c/dom/Node.java, external/w3c_dom/org/w3c/dom/NodeList.java, external/w3c_dom/org/w3c/dom/Notation.java, external/w3c_dom/org/w3c/dom/ProcessingInstruction.java, external/w3c_dom/org/w3c/dom/Text.java, external/w3c_dom/org/w3c/dom/TypeInfo.java, external/w3c_dom/org/w3c/dom/UserDataHandler.java, external/w3c_dom/org/w3c/dom/bootstrap/DOMImplementationRegistry.java, external/w3c_dom/org/w3c/dom/css/CSS2Properties.java, external/w3c_dom/org/w3c/dom/css/CSSCharsetRule.java, external/w3c_dom/org/w3c/dom/css/CSSFontFaceRule.java, external/w3c_dom/org/w3c/dom/css/CSSImportRule.java, external/w3c_dom/org/w3c/dom/css/CSSMediaRule.java, external/w3c_dom/org/w3c/dom/css/CSSPageRule.java, external/w3c_dom/org/w3c/dom/css/CSSPrimitiveValue.java, external/w3c_dom/org/w3c/dom/css/CSSRule.java, external/w3c_dom/org/w3c/dom/css/CSSRuleList.java, external/w3c_dom/org/w3c/dom/css/CSSStyleDeclaration.java, external/w3c_dom/org/w3c/dom/css/CSSStyleRule.java, external/w3c_dom/org/w3c/dom/css/CSSStyleSheet.java, external/w3c_dom/org/w3c/dom/css/CSSUnknownRule.java, external/w3c_dom/org/w3c/dom/css/CSSValue.java, external/w3c_dom/org/w3c/dom/css/CSSValueList.java, external/w3c_dom/org/w3c/dom/css/Counter.java, external/w3c_dom/org/w3c/dom/css/DOMImplementationCSS.java, external/w3c_dom/org/w3c/dom/css/DocumentCSS.java, external/w3c_dom/org/w3c/dom/css/ElementCSSInlineStyle.java, external/w3c_dom/org/w3c/dom/css/RGBColor.java, external/w3c_dom/org/w3c/dom/css/Rect.java, external/w3c_dom/org/w3c/dom/css/ViewCSS.java, external/w3c_dom/org/w3c/dom/events/DocumentEvent.java, external/w3c_dom/org/w3c/dom/events/Event.java, external/w3c_dom/org/w3c/dom/events/EventException.java, external/w3c_dom/org/w3c/dom/events/EventListener.java, external/w3c_dom/org/w3c/dom/events/EventTarget.java, external/w3c_dom/org/w3c/dom/events/MouseEvent.java, external/w3c_dom/org/w3c/dom/events/MutationEvent.java, external/w3c_dom/org/w3c/dom/events/UIEvent.java, external/w3c_dom/org/w3c/dom/html2/HTMLAnchorElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLAppletElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLAreaElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLBRElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLBaseElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLBaseFontElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLBodyElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLButtonElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLCollection.java, external/w3c_dom/org/w3c/dom/html2/HTMLDListElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLDirectoryElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLDivElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLDocument.java, external/w3c_dom/org/w3c/dom/html2/HTMLElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLFieldSetElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLFontElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLFormElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLFrameElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLFrameSetElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLHRElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLHeadElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLHeadingElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLHtmlElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLIFrameElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLImageElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLInputElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLIsIndexElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLLIElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLLabelElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLLegendElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLLinkElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLMapElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLMenuElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLMetaElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLModElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLOListElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLObjectElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLOptGroupElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLOptionElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLOptionsCollection.java, external/w3c_dom/org/w3c/dom/html2/HTMLParagraphElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLParamElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLPreElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLQuoteElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLScriptElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLSelectElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLStyleElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLTableCaptionElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLTableCellElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLTableColElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLTableElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLTableRowElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLTableSectionElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLTextAreaElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLTitleElement.java, external/w3c_dom/org/w3c/dom/html2/HTMLUListElement.java, external/w3c_dom/org/w3c/dom/ls/DOMImplementationLS.java, external/w3c_dom/org/w3c/dom/ls/LSException.java, external/w3c_dom/org/w3c/dom/ls/LSInput.java, external/w3c_dom/org/w3c/dom/ls/LSLoadEvent.java, external/w3c_dom/org/w3c/dom/ls/LSOutput.java, external/w3c_dom/org/w3c/dom/ls/LSParser.java, external/w3c_dom/org/w3c/dom/ls/LSParserFilter.java, external/w3c_dom/org/w3c/dom/ls/LSProgressEvent.java, external/w3c_dom/org/w3c/dom/ls/LSResourceResolver.java, external/w3c_dom/org/w3c/dom/ls/LSSerializer.java, external/w3c_dom/org/w3c/dom/ls/LSSerializerFilter.java, external/w3c_dom/org/w3c/dom/ranges/DocumentRange.java, external/w3c_dom/org/w3c/dom/ranges/Range.java, external/w3c_dom/org/w3c/dom/ranges/RangeException.java, external/w3c_dom/org/w3c/dom/stylesheets/DocumentStyle.java, external/w3c_dom/org/w3c/dom/stylesheets/LinkStyle.java, external/w3c_dom/org/w3c/dom/stylesheets/MediaList.java, external/w3c_dom/org/w3c/dom/stylesheets/StyleSheet.java, external/w3c_dom/org/w3c/dom/stylesheets/StyleSheetList.java, external/w3c_dom/org/w3c/dom/traversal/DocumentTraversal.java, external/w3c_dom/org/w3c/dom/traversal/NodeFilter.java, external/w3c_dom/org/w3c/dom/traversal/NodeIterator.java, external/w3c_dom/org/w3c/dom/traversal/TreeWalker.java, external/w3c_dom/org/w3c/dom/views/AbstractView.java, external/w3c_dom/org/w3c/dom/views/DocumentView.java, external/w3c_dom/org/w3c/dom/xpath/XPathEvaluator.java, external/w3c_dom/org/w3c/dom/xpath/XPathException.java, external/w3c_dom/org/w3c/dom/xpath/XPathExpression.java, external/w3c_dom/org/w3c/dom/xpath/XPathNSResolver.java, external/w3c_dom/org/w3c/dom/xpath/XPathNamespace.java, external/w3c_dom/org/w3c/dom/xpath/XPathResult.java: New files from Classpath. From-SVN: r94577
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/* ContentHandler2.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.aelfred2;
|
||||
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Extension to the SAX ContentHandler interface to report parsing events
|
||||
* and parameters required by DOM Level 3 but not supported by SAX.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public interface ContentHandler2
|
||||
extends ContentHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Reports the XML declaration.
|
||||
* @param version the value of the version attribute in the XML
|
||||
* declaration
|
||||
* @param encoding the encoding specified in the XML declaration, if any
|
||||
* @param standalone the standalone attribute from the XML declaration
|
||||
* @param inputEncoding the encoding of the XML input
|
||||
*/
|
||||
void xmlDecl(String version, String encoding, boolean standalone,
|
||||
String inputEncoding)
|
||||
throws SAXException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/* JAXPFactory.java --
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.aelfred2;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.xml.sax.Parser;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
import org.xml.sax.helpers.XMLReaderAdapter;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Configurable factory to create an Ælfred2 JAXP parser; required
|
||||
* to bootstrap using JAXP. You should use SAX2 directly where possible,
|
||||
* rather than through JAXP, since that gives you better control.
|
||||
* This class would normally be configured as a platform default factory.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public final class JAXPFactory extends SAXParserFactory
|
||||
{
|
||||
private Hashtable flags = new Hashtable ();
|
||||
|
||||
/**
|
||||
* Constructs a factory which normally returns a non-validating
|
||||
* parser.
|
||||
*/
|
||||
public JAXPFactory () { }
|
||||
|
||||
public SAXParser newSAXParser ()
|
||||
throws ParserConfigurationException, SAXException
|
||||
{
|
||||
JaxpParser jaxp = new JaxpParser ();
|
||||
Enumeration e = flags.keys ();
|
||||
XMLReader parser = jaxp.getXMLReader ();
|
||||
|
||||
parser.setFeature (
|
||||
SAXDriver.FEATURE + "namespaces",
|
||||
isNamespaceAware ());
|
||||
parser.setFeature (
|
||||
SAXDriver.FEATURE + "validation",
|
||||
isValidating ());
|
||||
// that makes SAX2 feature flags trump JAXP
|
||||
|
||||
while (e.hasMoreElements ()) {
|
||||
String uri = (String) e.nextElement ();
|
||||
Boolean value = (Boolean) flags.get (uri);
|
||||
parser.setFeature (uri, value.booleanValue ());
|
||||
}
|
||||
|
||||
return jaxp;
|
||||
}
|
||||
|
||||
// yes, this "feature transfer" mechanism doesn't play well
|
||||
|
||||
public void setFeature (String name, boolean value)
|
||||
throws
|
||||
ParserConfigurationException,
|
||||
SAXNotRecognizedException,
|
||||
SAXNotSupportedException
|
||||
{
|
||||
try {
|
||||
// force "early" detection of errors where possible
|
||||
// (flags can't necessarily be set before parsing)
|
||||
new JaxpParser ().getXMLReader ().setFeature (name, value);
|
||||
|
||||
flags.put (name, new Boolean (value));
|
||||
} catch (SAXNotRecognizedException e) {
|
||||
throw new SAXNotRecognizedException (name);
|
||||
} catch (SAXNotSupportedException e) {
|
||||
throw new SAXNotSupportedException (name);
|
||||
} catch (Exception e) {
|
||||
throw new ParserConfigurationException (
|
||||
e.getClass ().getName ()
|
||||
+ ": "
|
||||
+ e.getMessage ());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getFeature (String name)
|
||||
throws
|
||||
ParserConfigurationException,
|
||||
SAXNotRecognizedException,
|
||||
SAXNotSupportedException
|
||||
{
|
||||
Boolean value = (Boolean) flags.get (name);
|
||||
|
||||
if (value != null)
|
||||
return value.booleanValue ();
|
||||
else
|
||||
try {
|
||||
return new JaxpParser ().getXMLReader ().getFeature (name);
|
||||
} catch (SAXNotRecognizedException e) {
|
||||
throw new SAXNotRecognizedException (name);
|
||||
} catch (SAXNotSupportedException e) {
|
||||
throw new SAXNotSupportedException (name);
|
||||
} catch (SAXException e) {
|
||||
throw new ParserConfigurationException (
|
||||
e.getClass ().getName ()
|
||||
+ ": "
|
||||
+ e.getMessage ());
|
||||
}
|
||||
}
|
||||
|
||||
private static class JaxpParser extends SAXParser
|
||||
{
|
||||
private XmlReader ae2 = new XmlReader ();
|
||||
private XMLReaderAdapter parser = null;
|
||||
|
||||
JaxpParser () { }
|
||||
|
||||
public void setProperty (String id, Object value)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException
|
||||
{ ae2.setProperty (id, value); }
|
||||
|
||||
public Object getProperty (String id)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException
|
||||
{ return ae2.getProperty (id); }
|
||||
|
||||
public Parser getParser ()
|
||||
throws SAXException
|
||||
{
|
||||
if (parser == null)
|
||||
parser = new XMLReaderAdapter (ae2);
|
||||
return parser;
|
||||
}
|
||||
|
||||
public XMLReader getXMLReader ()
|
||||
throws SAXException
|
||||
{ return ae2; }
|
||||
|
||||
public boolean isNamespaceAware ()
|
||||
{
|
||||
try {
|
||||
return ae2.getFeature (SAXDriver.FEATURE + "namespaces");
|
||||
} catch (Exception e) {
|
||||
throw new Error ();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isValidating ()
|
||||
{
|
||||
try {
|
||||
return ae2.getFeature (SAXDriver.FEATURE + "validation");
|
||||
} catch (Exception e) {
|
||||
throw new Error ();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO isXIncludeAware()
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,315 @@
|
||||
/* XmlReader.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.aelfred2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.ext.*;
|
||||
|
||||
import gnu.xml.pipeline.EventFilter;
|
||||
import gnu.xml.pipeline.ValidationConsumer;
|
||||
|
||||
|
||||
/**
|
||||
* This SAX2 parser optionally layers a validator over the Ælfred2
|
||||
* SAX2 parser. While this will not evaluate every XML validity constraint,
|
||||
* it does support all the validity constraints that are of any real utility
|
||||
* outside the strict SGML-compatible world. See the documentation for the
|
||||
* SAXDriver class for information about the SAX2 features and properties
|
||||
* that are supported, and documentation for the ValidationConsumer for
|
||||
* information about what validity constraints may not be supported.
|
||||
* (Ælfred2 tests some of those, even in non-validating mode, to
|
||||
* achieve better conformance.)
|
||||
*
|
||||
* <p> Note that due to its internal construction, you can't change most
|
||||
* handlers until parse() returns. This diverges slightly from SAX, which
|
||||
* expects later binding to be supported. Early binding involves less
|
||||
* runtime overhead, which is an issue for event pipelines as used inside
|
||||
* this parser. Rather than relying on the parser to handle late binding
|
||||
* to your own handlers, do it yourself.
|
||||
*
|
||||
* @see SAXDriver
|
||||
* @see gnu.xml.pipeline.ValidationConsumer
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public final class XmlReader implements XMLReader
|
||||
{
|
||||
private SAXDriver aelfred2 = new SAXDriver ();
|
||||
private EventFilter filter = new EventFilter ();
|
||||
private boolean isValidating;
|
||||
private boolean active;
|
||||
|
||||
|
||||
/** Constructs a SAX Parser. */
|
||||
public XmlReader ()
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Constructs a SAX Parser, optionally treating validity errors
|
||||
* as if they were fatal errors.
|
||||
*/
|
||||
public XmlReader (boolean invalidIsFatal)
|
||||
{
|
||||
if (invalidIsFatal)
|
||||
setErrorHandler (new DefaultHandler2 () {
|
||||
public void error (SAXParseException e)
|
||||
throws SAXException
|
||||
{ throw e; }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Returns the object used to report the logical
|
||||
* content of an XML document.
|
||||
*/
|
||||
public ContentHandler getContentHandler ()
|
||||
{ return filter.getContentHandler (); }
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Assigns the object used to report the logical
|
||||
* content of an XML document.
|
||||
* @exception IllegalStateException if called mid-parse
|
||||
*/
|
||||
public void setContentHandler (ContentHandler handler)
|
||||
{
|
||||
if (active)
|
||||
throw new IllegalStateException ("already parsing");
|
||||
filter.setContentHandler (handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Returns the object used to process declarations related
|
||||
* to notations and unparsed entities.
|
||||
*/
|
||||
public DTDHandler getDTDHandler ()
|
||||
{ return filter.getDTDHandler (); }
|
||||
|
||||
/**
|
||||
* <b>SAX1</b> Assigns DTD handler
|
||||
* @exception IllegalStateException if called mid-parse
|
||||
*/
|
||||
public void setDTDHandler (DTDHandler handler)
|
||||
{
|
||||
if (active)
|
||||
throw new IllegalStateException ("already parsing");
|
||||
filter.setDTDHandler (handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Returns the object used when resolving external
|
||||
* entities during parsing (both general and parameter entities).
|
||||
*/
|
||||
public EntityResolver getEntityResolver ()
|
||||
{ return aelfred2.getEntityResolver (); }
|
||||
|
||||
/** <b>SAX1</b> Assigns parser's entity resolver */
|
||||
public void setEntityResolver (EntityResolver handler)
|
||||
{ aelfred2.setEntityResolver (handler); }
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Returns the object used to receive callbacks for XML
|
||||
* errors of all levels (fatal, nonfatal, warning); this is never null;
|
||||
*/
|
||||
public ErrorHandler getErrorHandler ()
|
||||
{ return aelfred2.getErrorHandler (); }
|
||||
|
||||
/**
|
||||
* <b>SAX1</b> Assigns error handler
|
||||
* @exception IllegalStateException if called mid-parse
|
||||
*/
|
||||
public void setErrorHandler (ErrorHandler handler)
|
||||
{
|
||||
if (active)
|
||||
throw new IllegalStateException ("already parsing");
|
||||
aelfred2.setErrorHandler (handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Assigns the specified property.
|
||||
* @exception IllegalStateException if called mid-parse
|
||||
*/
|
||||
public void setProperty (String propertyId, Object value)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException
|
||||
{
|
||||
if (active)
|
||||
throw new IllegalStateException ("already parsing");
|
||||
if (getProperty (propertyId) != value)
|
||||
filter.setProperty (propertyId, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Returns the specified property.
|
||||
*/
|
||||
public Object getProperty (String propertyId)
|
||||
throws SAXNotRecognizedException
|
||||
{
|
||||
if ((SAXDriver.PROPERTY + "declaration-handler")
|
||||
.equals (propertyId)
|
||||
|| (SAXDriver.PROPERTY + "lexical-handler")
|
||||
.equals (propertyId))
|
||||
return filter.getProperty (propertyId);
|
||||
throw new SAXNotRecognizedException (propertyId);
|
||||
}
|
||||
|
||||
private void forceValidating ()
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException
|
||||
{
|
||||
aelfred2.setFeature (
|
||||
SAXDriver.FEATURE + "namespace-prefixes",
|
||||
true);
|
||||
aelfred2.setFeature (
|
||||
SAXDriver.FEATURE + "external-general-entities",
|
||||
true);
|
||||
aelfred2.setFeature (
|
||||
SAXDriver.FEATURE + "external-parameter-entities",
|
||||
true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Sets the state of features supported in this parser.
|
||||
* Note that this parser requires reporting of namespace prefixes when
|
||||
* validating.
|
||||
*/
|
||||
public void setFeature (String featureId, boolean state)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException
|
||||
{
|
||||
boolean value = getFeature (featureId);
|
||||
|
||||
if (state == value)
|
||||
return;
|
||||
|
||||
if ((SAXDriver.FEATURE + "validation").equals (featureId)) {
|
||||
if (active)
|
||||
throw new SAXNotSupportedException ("already parsing");
|
||||
if (state)
|
||||
forceValidating ();
|
||||
isValidating = state;
|
||||
} else
|
||||
aelfred2.setFeature (featureId, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2</b>: Tells whether this parser supports the specified feature.
|
||||
* At this time, this directly parallels the underlying SAXDriver,
|
||||
* except that validation is optionally supported.
|
||||
*
|
||||
* @see SAXDriver
|
||||
*/
|
||||
public boolean getFeature (String featureId)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException
|
||||
{
|
||||
if ((SAXDriver.FEATURE + "validation").equals (featureId))
|
||||
return isValidating;
|
||||
|
||||
return aelfred2.getFeature (featureId);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX1</b>: Sets the locale used for diagnostics; currently,
|
||||
* only locales using the English language are supported.
|
||||
* @param locale The locale for which diagnostics will be generated
|
||||
*/
|
||||
public void setLocale (Locale locale)
|
||||
throws SAXException
|
||||
{ aelfred2.setLocale (locale); }
|
||||
|
||||
/**
|
||||
* <b>SAX1</b>: Preferred API to parse an XML document, using a
|
||||
* system identifier (URI).
|
||||
*/
|
||||
public void parse (String systemId)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
parse (new InputSource (systemId));
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX1</b>: Underlying API to parse an XML document, used
|
||||
* directly when no URI is available. When this is invoked,
|
||||
* and the parser is set to validate, some features will be
|
||||
* automatically reset to appropriate values: for reporting
|
||||
* namespace prefixes, and incorporating external entities.
|
||||
*
|
||||
* @param source The XML input source.
|
||||
*
|
||||
* @exception IllegalStateException if called mid-parse
|
||||
* @exception SAXException The handlers may throw any SAXException,
|
||||
* and the parser normally throws SAXParseException objects.
|
||||
* @exception IOException IOExceptions are normally through through
|
||||
* the parser if there are problems reading the source document.
|
||||
*/
|
||||
public void parse (InputSource source)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
EventFilter next;
|
||||
boolean nsdecls;
|
||||
|
||||
synchronized (aelfred2) {
|
||||
if (active)
|
||||
throw new IllegalStateException ("already parsing");
|
||||
active = true;
|
||||
}
|
||||
|
||||
// set up the output pipeline
|
||||
if (isValidating) {
|
||||
forceValidating ();
|
||||
next = new ValidationConsumer (filter);
|
||||
} else
|
||||
next = filter;
|
||||
|
||||
// connect pipeline and error handler
|
||||
// don't let _this_ call to bind() affect xmlns* attributes
|
||||
nsdecls = aelfred2.getFeature (
|
||||
SAXDriver.FEATURE + "namespace-prefixes");
|
||||
EventFilter.bind (aelfred2, next);
|
||||
if (!nsdecls)
|
||||
aelfred2.setFeature (
|
||||
SAXDriver.FEATURE + "namespace-prefixes",
|
||||
false);
|
||||
|
||||
// parse, clean up
|
||||
try {
|
||||
aelfred2.parse (source);
|
||||
} finally {
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,506 @@
|
||||
<!DOCTYPE html PUBLIC
|
||||
'-//W3C//DTD XHTML 1.0 Transitional//EN'
|
||||
'http://www.w3.org/TR/xhtml1/DTD/transitional.dtd'>
|
||||
|
||||
<html><head>
|
||||
<title>package overview</title>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 1999,2000,2001 The Free Software Foundation, Inc.
|
||||
*/
|
||||
-->
|
||||
</head><body>
|
||||
|
||||
<p> This package contains Ælfred2, which includes an
|
||||
enhanced SAX2-compatible version of the Ælfred
|
||||
non-validating XML parser, a modular (and hence optional)
|
||||
DTD validating parser, and modular (and hence optional)
|
||||
JAXP glue to those.
|
||||
Use these like any other SAX2 parsers. </p>
|
||||
|
||||
<ul>
|
||||
<li><a href="#about">About Ælfred</a><ul>
|
||||
<li><a href="#principles">Design Principles</a></li>
|
||||
<li><a href="#name">About the Name Ælfred</a></li>
|
||||
<li><a href="#encodings">Character Encodings</a></li>
|
||||
<li><a href="#violations">Known Conformance Violations</a></li>
|
||||
<li><a href="#copyright">Licensing</a></li>
|
||||
</ul></li>
|
||||
|
||||
<li><a href="#changes">Changes Since the Last Microstar Release</a><ul>
|
||||
<li><a href="#sax2">SAX2 Support</a></li>
|
||||
<li><a href="#validation">Validation</a></li>
|
||||
<li><a href="#smaller">You Want Smaller?</a></li>
|
||||
<li><a href="#bugfixes">Bugs Fixed</a></li>
|
||||
</ul></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2><a name="about">About Ælfred</a></h2>
|
||||
|
||||
<p>Ælfred is a XML parser written in the java programming language.
|
||||
|
||||
<h3><a name="principles">Design Principles</a></h3>
|
||||
|
||||
<p>In most Java applets and applications, XML should not be the central
|
||||
feature; instead, XML is the means to another end, such as loading
|
||||
configuration information, reading meta-data, or parsing transactions.</p>
|
||||
|
||||
<p> When an XML parser is only a single component of a much larger
|
||||
program, it cannot be large, slow, or resource-intensive. With Java
|
||||
applets, in particular, code size is a significant issue. The standard
|
||||
modem is still not operating at 56 Kbaud, or sometimes even with data
|
||||
compression. Assuming an uncompressed 28.8 Kbaud modem, only about
|
||||
3 KBytes can be downloaded in one second; compression often doubles
|
||||
that speed, but a V.90 modem may not provide another doubling. When
|
||||
used with embedded processors, similar size concerns apply. </p>
|
||||
|
||||
<p> Ælfred is designed for easy and efficient use over the Internet,
|
||||
based on the following principles: </p> <ol>
|
||||
|
||||
<li> Ælfred must be as small as possible, so that it doesn't add too
|
||||
much to an applet's download time. </li>
|
||||
|
||||
<li> Ælfred must use as few class files as possible, to minimize the
|
||||
number of HTTP connections necessary. (The use of JAR files has made this
|
||||
be less of a concern.) </li>
|
||||
|
||||
<li> Ælfred must be compatible with most or all Java implementations
|
||||
and platforms. (Write once, run anywhere.) </li>
|
||||
|
||||
<li> Ælfred must use as little memory as possible, so that it does
|
||||
not take away resources from the rest of your program. (It doesn't force
|
||||
you to use DOM or a similar costly data structure API.)</li>
|
||||
|
||||
<li> Ælfred must run as fast as possible, so that it does not slow down
|
||||
the rest of your program. </li>
|
||||
|
||||
<li> Ælfred must produce correct output for well-formed and valid
|
||||
documents, but need not reject every document that is not valid or
|
||||
not well-formed. (In Ælfred2, correctness was a bigger concern
|
||||
than in the original version; and a validation option is available.) </li>
|
||||
|
||||
<li> Ælfred must provide full internationalization from the first
|
||||
release. (Ælfred2 now automatically handles all encodings
|
||||
supported by the underlying JVM; previous versions handled only
|
||||
UTF-8, UTF_16, ASCII, and ISO-8859-1.)</li>
|
||||
|
||||
</ol>
|
||||
|
||||
<p>As you can see from this list, Ælfred is designed for production
|
||||
use, but neither validation nor perfect conformance was a requirement.
|
||||
Good validating parsers exist, including one in this package,
|
||||
and you should use them as appropriate. (See conformance reviews
|
||||
available at <a href="http://www.xml.com/">http://www.xml.com</a>)
|
||||
</p>
|
||||
|
||||
<p> One of the main goals of Ælfred2 was to significantly improve
|
||||
conformance, while not significantly affecting the other goals stated above.
|
||||
Since the only use of this parser is with SAX, some classes could be
|
||||
removed, and so the overall size of Ælfred was actually reduced.
|
||||
Subsequent performance work produced a notable speedup (over twenty
|
||||
percent on larger files). That is, the tradeoffs between speed, size, and
|
||||
conformance were re-targeted towards conformance and support of newer APIs
|
||||
(SAX2), with a a positive performance impact. </p>
|
||||
|
||||
<p> The role anticipated for this version of Ælfred is as a
|
||||
lightweight Free Software SAX parser that can be used in essentially every
|
||||
Java program where the handful of conformance violations (noted below)
|
||||
are acceptable.
|
||||
That certainly includes applets, and
|
||||
nowadays one must also mention embedded systems as being even more
|
||||
size-critical.
|
||||
At this writing, all parsers that are more conformant are
|
||||
significantly larger, even when counting the optional
|
||||
validation support in this version of Ælfred. </p>
|
||||
|
||||
|
||||
<h3><a name="name">About the Name <em>Ælfred</em></a></h3>
|
||||
|
||||
<p>Ælfred the Great (AElfred in ASCII) was King of Wessex, and
|
||||
some say of King of England, at the time of his death in 899 AD.
|
||||
Ælfred introduced a wide-spread literacy program in the hope that
|
||||
his people would learn to read English, at least, if Latin was too
|
||||
difficult for them. This Ælfred hopes to bring another sort of
|
||||
literacy to Java, using XML, at least, if full SGML is too difficult.</p>
|
||||
|
||||
<p>The initial Æ ligature ("AE)" is also a reminder that XML is
|
||||
not limited to ASCII.</p>
|
||||
|
||||
|
||||
<h3><a name="encodings">Character Encodings</a></h3>
|
||||
|
||||
<p> The Ælfred parser currently builds in support for a handful
|
||||
of input encodings. Of course these include UTF-8 and UTF-16, which
|
||||
all XML parsers are required to support:</p> <ul>
|
||||
|
||||
<li> UTF-8 ... the standard eight bit encoding, used unless
|
||||
you provide an encoding declaration or a MIME charset tag.</li>
|
||||
|
||||
<li> US-ASCII ... an extremely common seven bit encoding,
|
||||
which happens to be a subset of UTF-8 and ISO-8859-1 as well
|
||||
as many other encodings. XHTML web pages using US-ASCII
|
||||
(without an encoding declaration) are probably more
|
||||
widely interoperable than those in any other encoding. </li>
|
||||
|
||||
<li> ISO-8859-1 ... includes accented characters used in
|
||||
much of western Europe (but excluding the Euro currency
|
||||
symbol).</li>
|
||||
|
||||
<li> UTF-16 ... with several variants, this encodes each
|
||||
sixteen bit Unicode character in sixteen bits of output.
|
||||
Variants include UTF-16BE (big endian, no byte order mark),
|
||||
UTF-16LE (little endian, no byte order mark), and
|
||||
ISO-10646-UCS-2 (an older and less used encoding, using a
|
||||
version of Unicode without surrogate pairs). This is
|
||||
essentially the native encoding used by Java. </li>
|
||||
|
||||
<li> ISO-10646-UCS-4 ... a seldom-used four byte encoding,
|
||||
also known as UTF-32BE. Four byte order variants are supported,
|
||||
including one known as UTF-32LE. Some operating systems
|
||||
standardized on UCS-4 despite its significant size penalty,
|
||||
in anticipation that Unicode (even with surrogate pairs)
|
||||
would eventually become limiting. UCS-4 permits encoding
|
||||
of non-Unicode characters, which Java can't represent (and
|
||||
XML doesn't allow).
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> If you use any encoding other than UTF-8 or UTF-16 you should
|
||||
make sure to label your data appropriately: </p>
|
||||
|
||||
<blockquote>
|
||||
<?xml version="1.0" encoding="<b>ISO-8859-15</b>"?>
|
||||
</blockquote>
|
||||
|
||||
<p> Encodings accessed through <code>java.io.InputStreamReader</code>
|
||||
are now fully supported for both external labels (such as MIME types)
|
||||
and internal types (as shown above).
|
||||
There is one limitation in the support for internal labels:
|
||||
the encodings must be derived from the US-ASCII encoding,
|
||||
the EBCDIC family of encodings is not recognized.
|
||||
Note that Java defines its
|
||||
own encoding names, which don't always correspond to the standard
|
||||
Internet encoding names defined by the IETF/IANA, and that Java
|
||||
may even <em>require</em> use of nonstandard encoding names.
|
||||
Please report
|
||||
such problems; some of them can be worked around in this parser,
|
||||
and many can be worked around by using external labels.
|
||||
</p>
|
||||
|
||||
<p>Note that if you are using the Euro symbol with an fixed length
|
||||
eight bit encoding, you should probably be using the encoding label
|
||||
<em>iso-8859-15</em> or, with a Microsoft OS, <em>cp-1252</em>.
|
||||
Of course, UTF-8 and UTF-16 handle the Euro symbol directly.
|
||||
</p>
|
||||
|
||||
|
||||
<h3><a name="violations">Known Conformance Violations</a></h3>
|
||||
|
||||
<p>Known conformance issues should be of negligible importance for
|
||||
most applications, and include: </p><ul>
|
||||
|
||||
<li> Rather than following the voluminous "Appendix B" rules about
|
||||
what characters may appear in names (and name tokens), the Unicode
|
||||
rules embedded in <em>java.lang.Character</em> are used.
|
||||
This means mostly that some names are inappropriately accepted,
|
||||
though a few are inappropriately rejected. (It's much simpler
|
||||
to avoid that much special case code. Recent OASIS/NIST test
|
||||
cases may have these rules be realistically testable.) </li>
|
||||
|
||||
<li> Text containing "]]>" is not rejected unless it fully resides
|
||||
in an internal buffer ... which is, thankfully, the typical case. This
|
||||
text is illegal, but sometimes appears in illegal attempts to
|
||||
nest CDATA sections. (Not catching that boundary condition
|
||||
substantially simplifies parsing text.) </li>
|
||||
|
||||
<li> Surrogate characters that aren't correctly paired are ignored
|
||||
rather than rejected, unless they were encoded using UTF-8. (This
|
||||
simplifies parsing text.) Unicode 3.1 assigned the first characters
|
||||
to those character codes, in early 2001, so few documents (or tools)
|
||||
use such characters in any case. </li>
|
||||
|
||||
<li> Declarations following references to an undefined parameter
|
||||
entity reference are not ignored. (Not maintaining and using state
|
||||
about this validity error simplifies declaration handling; few
|
||||
XML parsers address this constraint in any case.) </li>
|
||||
|
||||
<li> Well formedness constraints for general entity references
|
||||
are not enforced. (The code to handle the "content" production
|
||||
is merged with the element parsing code, making it hard to reuse
|
||||
for this additional situation.) </li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> When tested against the July 12, 1999 version of the OASIS
|
||||
XML Conformance test suite, an earlier version passed 1057 of 1067 tests.
|
||||
That contrasts with the original version, which passed 867. The
|
||||
current parser is top-ranked in terms of conformance, as is its
|
||||
validating sibling (which has some additional conformance violations
|
||||
imposed on it by SAX2 API deficiencies as well as some of the more
|
||||
curious SGML layering artifacts found in the XML specification). </p>
|
||||
|
||||
<p> The XML 1.0 specification itself was not without problems,
|
||||
and after some delays the W3C has come out with a revised
|
||||
"second edition" specification. While that doesn't resolve all
|
||||
the problems identified the XML specification, many of the most
|
||||
egregious problems have been resolved. (You still need to drink
|
||||
magic Kool-Aid before some DTD-related issues make sense.)
|
||||
To the extent possible, this parser conforms to that second
|
||||
edition specification, and does well against corrected versions
|
||||
of the OASIS/NIST XML conformance test cases. See <a href=
|
||||
"http://xmlconf.sourceforge.net">http://xmlconf.sourceforge.net</a>
|
||||
for more information about SAX2/XML conformance testing. </p>
|
||||
|
||||
|
||||
<h3><a name="copyright">Copyright and distribution terms</a></h3>
|
||||
|
||||
<p>
|
||||
The software in this package is distributed under the GNU General Public
|
||||
License (with a special exception described below).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A copy of GNU General Public License (GPL) is included in this distribution,
|
||||
in the file COPYING. If you do not have the source code, it is available at:
|
||||
|
||||
<a href="http://www.gnu.org/software/classpath/">http://www.gnu.org/software/classpath/</a>
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
Parts derived from code which carried the following notice:
|
||||
|
||||
Copyright (c) 1997, 1998 by Microstar Software Ltd.
|
||||
|
||||
AElfred is free for both commercial and non-commercial use and
|
||||
redistribution, provided that Microstar's copyright and disclaimer are
|
||||
retained intact. You are free to modify AElfred for your own use and
|
||||
to redistribute AElfred with your modifications, provided that the
|
||||
modifications are clearly documented.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
merchantability or fitness for a particular purpose. Please use it AT
|
||||
YOUR OWN RISK.
|
||||
</pre>
|
||||
|
||||
<p> Some of this documentation was modified from the original
|
||||
Ælfred README.txt file. All of it has been updated. </p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
<h2><a name="changes">Changes Since the last Microstar Release</a></h2>
|
||||
|
||||
<p> As noted above, Microstar has not updated this parser since
|
||||
the summer of 1998, when it released version 1.2a on its web site.
|
||||
This release is intended to benefit the developer community by
|
||||
refocusing the API on SAX2, and improving conformance to the extent
|
||||
that most developers should not need to use another XML parser. </p>
|
||||
|
||||
<p> The code has been cleaned up (referring to the XML 1.0 spec in
|
||||
all the production numbers in
|
||||
comments, rather than some preliminary draft, for one example) and
|
||||
has been sped up a bit as well.
|
||||
JAXP support has been added, although developers are still
|
||||
strongly encouraged to use the SAX2 APIs directly. </p>
|
||||
|
||||
|
||||
<h3><a name="sax2">SAX2 Support</a></h3>
|
||||
|
||||
<p> The original version of Ælfred did not support the
|
||||
SAX2 APIs. </p>
|
||||
|
||||
<p> This version supports the SAX2 APIs, exposing the standard
|
||||
boolean feature descriptors. It supports the "DeclHandler" property
|
||||
to provide access to all DTD declarations not already exposed
|
||||
through the SAX1 API. The "LexicalHandler" property is supported,
|
||||
exposing entity boundaries (including the unnamed external subset) and
|
||||
things like comments and CDATA boundaries. SAX1 compatibility is
|
||||
currently provided.</p>
|
||||
|
||||
|
||||
<h3><a name="validation">Validation</a></h3>
|
||||
|
||||
<p> In the 'pipeline' package in this same software distribution is an
|
||||
<a href="../pipeline/ValidationConsumer.html">XML Validation component</a>
|
||||
using any full SAX2 event stream (including all document type declarations)
|
||||
to validate. There is now a <a href="XmlReader.html">XmlReader</a> class
|
||||
which combines that class and this enhanced Ælfred parser, creating
|
||||
an optionally validating SAX2 parser. </p>
|
||||
|
||||
<p> As noted in the documentation for that validating component, certain
|
||||
validity constraints can't reliably be tested by a layered validator.
|
||||
These include all constraints relying on
|
||||
layering violations (exposing XML at the level of tokens or below,
|
||||
required since XML isn't a context-free grammar), some that
|
||||
SAX2 doesn't support, and a few others. The resulting validating
|
||||
parser is conformant enough for most applications that aren't doing
|
||||
strange SGML tricks with DTDs.
|
||||
Moreover, that validating filter can be used without
|
||||
a parser ... any application component that emits SAX event streams
|
||||
can DTD-validate its output on demand. </p>
|
||||
|
||||
<h3><a name="smaller">You want Smaller?</a></h3>
|
||||
|
||||
<p> You'll have noticed that the original version of Ælfred
|
||||
had small size as a top goal. Ælfred2 normally includes a
|
||||
DTD validation layer, but you can package without that.
|
||||
Similarly, JAXP factory support is available but optional.
|
||||
Then the main added cost due to this revision are for
|
||||
supporting the SAX2 API itself; DTD validation is as
|
||||
cleanly layered as allowed by SAX2.</p>
|
||||
|
||||
<h3><a name="bugfixes">Bugs Fixed</a></h3>
|
||||
|
||||
<p> Bugs fixed in Ælfred2 include: </p>
|
||||
|
||||
<ol>
|
||||
<li> Originally Ælfred didn't close file descriptors, which
|
||||
led to file descriptor leakage on programs which ran for any
|
||||
length of time. </li>
|
||||
|
||||
<li> NOTATION declarations without system identifiers are
|
||||
now handled correctly. </li>
|
||||
|
||||
<li> DTD events are now reported for all invocations of a
|
||||
given parser, not just the first one. </li>
|
||||
|
||||
<li> More correct character handling: <ul>
|
||||
|
||||
<li> Rejects out-of-range characters, both in text and in
|
||||
character references. </li>
|
||||
|
||||
<li> Correctly handles character references that expand to
|
||||
surrogate pairs. </li>
|
||||
|
||||
<li> Correctly handles UTF-8 encodings of surrogate pairs. </li>
|
||||
|
||||
<li> Correctly handles Unicode 3.1 rules about illegal UTF-8
|
||||
encodings: there is only one legal encoding per character. </li>
|
||||
|
||||
<li> PUBLIC identifiers are now rejected if they have illegal
|
||||
characters. </li>
|
||||
|
||||
<li> The parser is more correct about what characters are allowed
|
||||
in names and name tokens. Uses Unicode rules (built in to Java)
|
||||
rather than the voluminous XML rules, although some extensions
|
||||
have been made to match XML rules more closely.</li>
|
||||
|
||||
<li> Line ends are now normalized to newlines in all known
|
||||
cases. </li>
|
||||
|
||||
</ul></li>
|
||||
|
||||
<li> Certain validity errors were previously treated as well
|
||||
formedness violations. <ul>
|
||||
|
||||
<li> Repeated declarations of an element type are no
|
||||
longer fatal errors. </li>
|
||||
|
||||
<li> Undeclared parameter entity references are no longer
|
||||
fatal errors. </li>
|
||||
|
||||
</ul></li>
|
||||
|
||||
<li> Attribute handling is improved: <ul>
|
||||
|
||||
<li> Whitespace must exist between attributes. </li>
|
||||
|
||||
<li> Only one value for a given attribute is permitted. </li>
|
||||
|
||||
<li> ATTLIST declarations don't need to declare attributes. </li>
|
||||
|
||||
<li> Attribute values are normalized when required. </li>
|
||||
|
||||
<li> Tabs in attribute values are normalized to spaces. </li>
|
||||
|
||||
<li> Attribute values containing a literal "<" are rejected. </li>
|
||||
|
||||
</ul></li>
|
||||
|
||||
<li> More correct entity handling: <ul>
|
||||
|
||||
<li> Whitespace must precede NDATA when declaring unparsed
|
||||
entities.</li>
|
||||
|
||||
<li> Parameter entity declarations may not have NDATA annotations. </li>
|
||||
|
||||
<li> The XML specification has a bug in that it doesn't specify
|
||||
that certain contexts exist within which parameter entity
|
||||
expansion must not be performed. Lacking an offical erratum,
|
||||
this parser now disables such expansion inside comments,
|
||||
processing instructions, ignored sections, public identifiers,
|
||||
and parts of entity declarations. </li>
|
||||
|
||||
<li> Entity expansions that include quote characters no longer
|
||||
confuse parsing of strings using such expansions. </li>
|
||||
|
||||
<li> Whitespace in the values of internal entities is not mapped
|
||||
to space characters. </li>
|
||||
|
||||
<li> General Entity references in attribute defaults within the
|
||||
DTD now cause fatal errors when the entity is not defined at the
|
||||
time it is referenced. </li>
|
||||
|
||||
<li> Malformed general entity references in entity declarations are
|
||||
now detected. </li>
|
||||
|
||||
</ul></li>
|
||||
|
||||
<li> Neither conditional sections
|
||||
nor parameter entity references within markup declarations
|
||||
are permitted in the internal subset. </li>
|
||||
|
||||
<li> Processing instructions whose target names are "XML"
|
||||
(ignoring case) are now rejected. </li>
|
||||
|
||||
<li> Comments may not include "--".</li>
|
||||
|
||||
<li> Most "]]>" sequences in text are rejected. </li>
|
||||
|
||||
<li> Correct syntax for standalone declarations is enforced. </li>
|
||||
|
||||
<li> Setting a locale for diagnostics only produces an exception
|
||||
if the language of that locale isn't English. </li>
|
||||
|
||||
<li> Some more encoding names are recognized. These include the
|
||||
Unicode 3.0 variants of UTF-16 (UTF-16BE, UTF-16LE) as well as
|
||||
US-ASCII and a few commonly seen synonyms. </li>
|
||||
|
||||
<li> Text (from character content, PIs, or comments) large enough
|
||||
not to fit into internal buffers is now handled correctly even in
|
||||
some cases which were originally handled incorrectly.</li>
|
||||
|
||||
<li> Content is now reported for element types for which attributes
|
||||
have been declared, but no content model is known. (Such documents
|
||||
are invalid, but may still be well formed.) </li>
|
||||
|
||||
</ol>
|
||||
|
||||
<p> Other bugs may also have been fixed. </p>
|
||||
|
||||
<p> For better overall validation support, some of the validity
|
||||
constraints that can't be verified using the SAX2 event stream
|
||||
are now reported directly by Ælfred2. </p>
|
||||
|
||||
</body></html>
|
||||
|
||||
@@ -0,0 +1,373 @@
|
||||
/* Consumer.java --
|
||||
Copyright (C) 2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.Attributes2;
|
||||
|
||||
import gnu.xml.pipeline.DomConsumer;
|
||||
import gnu.xml.pipeline.EventConsumer;
|
||||
|
||||
|
||||
/**
|
||||
* Event consumer which constructs DOM documents using the implementation
|
||||
* in this package, using SAX2 events. This packages various backdoors
|
||||
* into this DOM implementation, as needed to address DOM requirements
|
||||
* that can't be met by strictly conforming implementations of DOM.
|
||||
*
|
||||
* <p> These requirements all relate to {@link DocumentType} nodes and
|
||||
* features of that node type. These features are normally not used,
|
||||
* because that interface only exposes a subset of the information found
|
||||
* in DTDs. More, that subset does not include the most important typing
|
||||
* information. For example, it excludes element content models and
|
||||
* attribute typing. It does expose some entity management issues,
|
||||
* although entity management doesn't relate to document typing.
|
||||
*
|
||||
* <p> Note that SAX2 does not expose the literal text of the DTD's
|
||||
* internal subset, so it will not be present in DOM trees constructed
|
||||
* using this API. (Though with a good SAX2 implementation, it could
|
||||
* be partially recreated...)
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class Consumer extends DomConsumer
|
||||
{
|
||||
/**
|
||||
* Constructs an unconfigured event consumer,
|
||||
* as a terminus in a SAX event pipeline.
|
||||
*/
|
||||
// used by PipelineFactory [terminus]
|
||||
public Consumer ()
|
||||
throws SAXException
|
||||
{
|
||||
super (DomDocument.class);
|
||||
setHandler (new Backdoor (this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an unconfigured event consumer,
|
||||
* as a stage in a SAX event pipeline.
|
||||
*/
|
||||
// used by PipelineFactory [filter]
|
||||
public Consumer (EventConsumer next)
|
||||
throws SAXException
|
||||
{
|
||||
super (DomDocument.class, next);
|
||||
setHandler (new Backdoor (this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the backdoors needed by DOM.
|
||||
* All methods in this class use implementation-specific APIs that are
|
||||
* implied by the DOM specification (needed to implement testable
|
||||
* behavior) but which are excluded from the DOM specification.
|
||||
*/
|
||||
public static class Backdoor extends DomConsumer.Handler
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
* @param consumer must have been initialized to use the
|
||||
* {@link DomDocument} class (or a subclass) for
|
||||
* constructing DOM trees
|
||||
*/
|
||||
protected Backdoor (DomConsumer consumer)
|
||||
throws SAXException
|
||||
{ super (consumer); }
|
||||
|
||||
// helper routine
|
||||
private DomDoctype getDoctype ()
|
||||
throws SAXException
|
||||
{
|
||||
DomDocument doc = (DomDocument) getDocument ();
|
||||
DocumentType dt = doc.getDoctype ();
|
||||
|
||||
if (dt == null)
|
||||
throw new SAXException ("doctype missing!");
|
||||
return (DomDoctype) dt;
|
||||
}
|
||||
|
||||
// SAX2 "lexical" event
|
||||
public void startDTD (String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
DomDocument doc = (DomDocument) getDocument ();
|
||||
|
||||
super.startDTD (name, publicId, systemId);
|
||||
// DOM L2 doctype creation model is bizarre
|
||||
DomDoctype dt = new DomDoctype (doc, name, publicId, systemId);
|
||||
doc.appendChild (dt);
|
||||
}
|
||||
|
||||
// SAX2 "lexical" event
|
||||
public void endDTD ()
|
||||
throws SAXException
|
||||
{
|
||||
super.endDTD ();
|
||||
// DOM L2 has no way to make things readonly
|
||||
getDoctype ().makeReadonly ();
|
||||
}
|
||||
|
||||
// SAX1 DTD event
|
||||
public void notationDecl (
|
||||
String name,
|
||||
String publicId, String systemId
|
||||
) throws SAXException
|
||||
{
|
||||
// DOM L2 can't create/save notation nodes
|
||||
getDoctype ().declareNotation (name, publicId, systemId);
|
||||
}
|
||||
|
||||
// SAX1 DTD event
|
||||
public void unparsedEntityDecl (
|
||||
String name,
|
||||
String publicId, String systemId,
|
||||
String notationName
|
||||
) throws SAXException
|
||||
{
|
||||
// DOM L2 can't create/save entity nodes
|
||||
getDoctype ().declareEntity (name, publicId, systemId,
|
||||
notationName);
|
||||
}
|
||||
|
||||
// SAX2 declaration event
|
||||
public void internalEntityDecl (String name, String value)
|
||||
throws SAXException
|
||||
{
|
||||
// DOM L2 can't create/save entity nodes
|
||||
// NOTE: this doesn't save the value as a child of this
|
||||
// node, though it could realistically do so.
|
||||
getDoctype ().declareEntity (name, null, null, null);
|
||||
}
|
||||
|
||||
// SAX2 declaration event
|
||||
public void externalEntityDecl (
|
||||
String name,
|
||||
String publicId,
|
||||
String systemId
|
||||
) throws SAXException
|
||||
{
|
||||
// DOM L2 can't create/save entity nodes
|
||||
// NOTE: DOM allows for these to have children, if
|
||||
// they don't have unbound namespace references.
|
||||
getDoctype ().declareEntity (name, publicId, systemId, null);
|
||||
}
|
||||
|
||||
// SAX2 element
|
||||
public void startElement (
|
||||
String uri,
|
||||
String localName,
|
||||
String qName,
|
||||
Attributes atts
|
||||
) throws SAXException
|
||||
{
|
||||
Node top;
|
||||
|
||||
super.startElement (uri, localName, qName, atts);
|
||||
|
||||
// might there be more work?
|
||||
top = getTop ();
|
||||
if (!top.hasAttributes () || !(atts instanceof Attributes2))
|
||||
return;
|
||||
|
||||
// remember any attributes that got defaulted
|
||||
DomNamedNodeMap map = (DomNamedNodeMap) top.getAttributes ();
|
||||
Attributes2 attrs = (Attributes2) atts;
|
||||
int length = atts.getLength ();
|
||||
|
||||
//map.compact ();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (attrs.isSpecified (i))
|
||||
continue;
|
||||
|
||||
// value was defaulted.
|
||||
String temp = attrs.getQName (i);
|
||||
DomAttr attr;
|
||||
|
||||
if ("".equals (temp))
|
||||
attr = (DomAttr) map.getNamedItemNS (attrs.getURI (i),
|
||||
atts.getLocalName (i));
|
||||
else
|
||||
attr = (DomAttr) map.getNamedItem (temp);
|
||||
|
||||
// DOM L2 can't write this flag, only read it
|
||||
attr.setSpecified (false);
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement (
|
||||
String uri,
|
||||
String localName,
|
||||
String qName
|
||||
) throws SAXException
|
||||
{
|
||||
DomNode top = (DomNode) getTop ();
|
||||
top.compact ();
|
||||
super.endElement (uri, localName, qName);
|
||||
}
|
||||
|
||||
protected Text createText (
|
||||
boolean isCDATA,
|
||||
char buf [],
|
||||
int off,
|
||||
int len
|
||||
) {
|
||||
DomDocument doc = (DomDocument) getDocument ();
|
||||
|
||||
if (isCDATA)
|
||||
return doc.createCDATASection (buf, off, len);
|
||||
else
|
||||
return doc.createTextNode (buf, off, len);
|
||||
}
|
||||
|
||||
public void elementDecl(String name, String model)
|
||||
throws SAXException
|
||||
{
|
||||
getDoctype().elementDecl(name, model);
|
||||
}
|
||||
|
||||
public void attributeDecl (
|
||||
String ename,
|
||||
String aname,
|
||||
String type,
|
||||
String mode,
|
||||
String value
|
||||
) throws SAXException
|
||||
{
|
||||
getDoctype().attributeDecl(ename, aname, type, mode, value);
|
||||
/*
|
||||
if (value == null && !"ID".equals (type))
|
||||
return;
|
||||
|
||||
DomDoctype.ElementInfo info;
|
||||
|
||||
info = getDoctype ().getElementInfo (ename);
|
||||
if (value != null)
|
||||
info.setAttrDefault (aname, value);
|
||||
if ("ID".equals (type))
|
||||
info.setIdAttr (aname);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
// force duplicate name checking off while we're
|
||||
// using parser output (don't duplicate the work)
|
||||
public void startDocument () throws SAXException
|
||||
{
|
||||
super.startDocument ();
|
||||
|
||||
DomDocument doc = (DomDocument) getDocument ();
|
||||
doc.setStrictErrorChecking(false);
|
||||
doc.setBuilding(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Required by DOM Level 3 to report document parameters
|
||||
*/
|
||||
public void xmlDecl(String version,
|
||||
String encoding,
|
||||
boolean standalone,
|
||||
String inputEncoding)
|
||||
throws SAXException
|
||||
{
|
||||
super.xmlDecl(version, encoding, standalone, inputEncoding);
|
||||
|
||||
DomDocument doc = (DomDocument) getDocument();
|
||||
doc.setXmlEncoding(encoding);
|
||||
doc.setInputEncoding(inputEncoding);
|
||||
}
|
||||
|
||||
public void endDocument ()
|
||||
throws SAXException
|
||||
{
|
||||
DomDocument doc = (DomDocument) getDocument ();
|
||||
doc.setStrictErrorChecking(true);
|
||||
doc.setBuilding(false);
|
||||
doc.compact ();
|
||||
DomDoctype doctype = (DomDoctype) doc.getDoctype();
|
||||
if (doctype != null)
|
||||
{
|
||||
doctype.makeReadonly();
|
||||
}
|
||||
super.endDocument ();
|
||||
}
|
||||
|
||||
// these three methods collaborate to populate entity
|
||||
// refs, marking contents readonly on end-of-entity
|
||||
|
||||
public boolean canPopulateEntityRefs ()
|
||||
{ return true; }
|
||||
|
||||
public void startEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
if (name.charAt (0) == '%' || "[dtd]".equals (name))
|
||||
return;
|
||||
super.startEntity (name);
|
||||
|
||||
DomNode top = (DomNode) getTop ();
|
||||
|
||||
if (top.getNodeType () == Node.ENTITY_REFERENCE_NODE)
|
||||
top.readonly = false;
|
||||
}
|
||||
|
||||
public void endEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
if (name.charAt (0) == '%' || "[dtd]".equals (name))
|
||||
return;
|
||||
DomNode top = (DomNode) getTop ();
|
||||
|
||||
if (top.getNodeType () == Node.ENTITY_REFERENCE_NODE) {
|
||||
top.compact ();
|
||||
top.makeReadonly ();
|
||||
}
|
||||
super.endEntity (name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/* DTDAttributeTypeInfo.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.TypeInfo;
|
||||
|
||||
/**
|
||||
* Attribute type information supplied by a DTD attribute declaration.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DTDAttributeTypeInfo
|
||||
implements TypeInfo
|
||||
{
|
||||
|
||||
final String elementName;
|
||||
final String name;
|
||||
final String type;
|
||||
final String mode;
|
||||
final String value;
|
||||
|
||||
DTDAttributeTypeInfo(String elementName, String name, String type,
|
||||
String mode, String value)
|
||||
{
|
||||
this.elementName = elementName;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.mode = mode;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public final String getTypeName()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public final String getTypeNamespace()
|
||||
{
|
||||
return "http://www.w3.org/TR/REC-xml";
|
||||
}
|
||||
|
||||
public final boolean isDerivedFrom(String typeNamespace, String typeName,
|
||||
int derivationMethod)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/* DTDElementTypeInfo.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import org.w3c.dom.TypeInfo;
|
||||
|
||||
/**
|
||||
* Element type information provided by a DTD element declaration.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DTDElementTypeInfo
|
||||
implements TypeInfo
|
||||
{
|
||||
|
||||
final String name;
|
||||
String model;
|
||||
HashMap attributes;
|
||||
String idAttrName;
|
||||
|
||||
DTDElementTypeInfo(String name, String model)
|
||||
{
|
||||
this.name = name;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public final String getTypeName()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public final String getTypeNamespace()
|
||||
{
|
||||
return "http://www.w3.org/TR/REC-xml";
|
||||
}
|
||||
|
||||
public final boolean isDerivedFrom(String typeNamespace, String typeName,
|
||||
int derivationMethod)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DTDAttributeTypeInfo getAttributeTypeInfo(String name)
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return (DTDAttributeTypeInfo) attributes.get(name);
|
||||
}
|
||||
|
||||
void setAttributeTypeInfo(String name, DTDAttributeTypeInfo info)
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
attributes = new HashMap();
|
||||
}
|
||||
attributes.put(name, info);
|
||||
if ("ID".equals(info.type))
|
||||
{
|
||||
idAttrName = name;
|
||||
}
|
||||
}
|
||||
|
||||
Iterator attributes()
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return attributes.values().iterator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,379 @@
|
||||
/* DomAttr.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.TypeInfo;
|
||||
import org.w3c.dom.events.MutationEvent;
|
||||
|
||||
|
||||
/**
|
||||
* <p> "Attr" implementation. In DOM, attributes cost quite a lot of
|
||||
* memory because their values are complex structures rather than just
|
||||
* simple strings. To reduce your costs, avoid having more than one
|
||||
* child of an attribute; stick to a single Text node child, and ignore
|
||||
* even that by using the attribute's "nodeValue" property.</p>
|
||||
*
|
||||
* <p> As a bit of general advice, only look at attribute modification
|
||||
* events through the DOMAttrModified event (sent to the associated
|
||||
* element). Implementations are not guaranteed to report other events
|
||||
* in the same order, so you're very likely to write nonportable code if
|
||||
* you monitor events at the "children of Attr" level.</p>
|
||||
*
|
||||
* <p> At this writing, not all attribute modifications will cause the
|
||||
* DOMAttrModified event to be triggered ... only the ones using the string
|
||||
* methods (setNodeValue, setValue, and Element.setAttribute) to modify
|
||||
* those values. That is, if you manipulate those children directly,
|
||||
* elements won't get notified that attribute values have changed.
|
||||
* The natural fix for that will report other modifications, but won't
|
||||
* be able to expose "previous" attribute value; it'll need to be cached
|
||||
* or something (at which point why bother using child nodes). </p>
|
||||
*
|
||||
* <p><em>You are strongly advised not to use "children" of any attribute
|
||||
* nodes you work with.</em> </p>
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomAttr
|
||||
extends DomNsNode
|
||||
implements Attr
|
||||
{
|
||||
|
||||
private boolean specified;
|
||||
private String value; // string value cache
|
||||
|
||||
/**
|
||||
* Constructs an Attr node associated with the specified document.
|
||||
* The "specified" flag is initialized to true, since this DOM has
|
||||
* no current "back door" mechanisms to manage default values so
|
||||
* that every value must effectively be "specified".
|
||||
*
|
||||
* <p>This constructor should only be invoked by a Document as part of
|
||||
* its createAttribute functionality, or through a subclass which is
|
||||
* similarly used in a "Sub-DOM" style layer.
|
||||
*
|
||||
* @param owner The document with which this node is associated
|
||||
* @param namespaceURI Combined with the local part of the name,
|
||||
* this is used to uniquely identify a type of attribute
|
||||
* @param name Name of this attribute, which may include a prefix
|
||||
*/
|
||||
protected DomAttr(DomDocument owner, String namespaceURI, String name)
|
||||
{
|
||||
super(ATTRIBUTE_NODE, owner, namespaceURI, name);
|
||||
specified = true;
|
||||
length = 1;
|
||||
|
||||
// XXX register self to get insertion/removal events
|
||||
// and character data change events and when they happen,
|
||||
// report self-mutation
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the attribute name (same as getNodeName)
|
||||
*/
|
||||
public final String getName()
|
||||
{
|
||||
return getNodeName();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns true if a parser reported this was in the source text.
|
||||
*/
|
||||
public final boolean getSpecified()
|
||||
{
|
||||
return specified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records whether this attribute was in the source text.
|
||||
*/
|
||||
public final void setSpecified(boolean value)
|
||||
{
|
||||
specified = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the attribute value, with character and entity
|
||||
* references substituted.
|
||||
* <em>NOTE: entity refs as children aren't currently handled.</em>
|
||||
*/
|
||||
public String getNodeValue()
|
||||
{
|
||||
// If we have a simple node-value, use that
|
||||
if (first == null)
|
||||
{
|
||||
return (value == null) ? "" : value;
|
||||
}
|
||||
// Otherwise collect child node-values
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (DomNode ctx = first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
switch (ctx.nodeType)
|
||||
{
|
||||
case Node.TEXT_NODE:
|
||||
buf.append(ctx.getNodeValue());
|
||||
break;
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Assigns the value of the attribute; it will have one child,
|
||||
* which is a text node with the specified value (same as
|
||||
* setNodeValue).
|
||||
*/
|
||||
public final void setValue(String value)
|
||||
{
|
||||
setNodeValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the value of the attribute as a non-null string; same
|
||||
* as getNodeValue.
|
||||
* <em>NOTE: entity refs as children aren't currently handled.</em>
|
||||
*/
|
||||
public final String getValue()
|
||||
{
|
||||
return getNodeValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Assigns the attribute value; using this API, no entity or
|
||||
* character references will exist.
|
||||
* Causes a DOMAttrModified mutation event to be sent.
|
||||
*/
|
||||
public void setNodeValue(String value)
|
||||
{
|
||||
if (readonly)
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
if (value == null)
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
String oldValue = getNodeValue();
|
||||
while (last != null)
|
||||
{
|
||||
removeChild(last);
|
||||
}
|
||||
// don't create a new node just for this...
|
||||
/*
|
||||
Node text = owner.createTextNode(value);
|
||||
appendChild(text);
|
||||
*/
|
||||
this.value = value;
|
||||
length = 1;
|
||||
specified = true;
|
||||
|
||||
mutating(oldValue, value, MutationEvent.MODIFICATION);
|
||||
}
|
||||
|
||||
public final Node getFirstChild()
|
||||
{
|
||||
// Create a child text node if necessary
|
||||
if (first == null)
|
||||
{
|
||||
length = 0;
|
||||
Node text = owner.createTextNode((value == null) ? "" : value);
|
||||
appendChild(text);
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
public final Node getLastChild()
|
||||
{
|
||||
// Create a child text node if necessary
|
||||
if (last == null)
|
||||
{
|
||||
length = 0;
|
||||
Node text = owner.createTextNode((value == null) ? "" : value);
|
||||
appendChild(text);
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
public Node item(int index)
|
||||
{
|
||||
// Create a child text node if necessary
|
||||
if (first == null)
|
||||
{
|
||||
length = 0;
|
||||
Node text = owner.createTextNode((value == null) ? "" : value);
|
||||
appendChild(text);
|
||||
}
|
||||
return super.item(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the element with which this attribute is associated.
|
||||
*/
|
||||
public final Element getOwnerElement()
|
||||
{
|
||||
return (Element) parent;
|
||||
}
|
||||
|
||||
public final Node getNextSibling()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Node getPreviousSibling()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Node getParentNode()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the element with which this attribute is associated.
|
||||
*/
|
||||
public final void setOwnerElement(Element e)
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
|
||||
}
|
||||
if (!(e instanceof DomElement))
|
||||
{
|
||||
throw new DomEx(DomEx.WRONG_DOCUMENT_ERR);
|
||||
}
|
||||
parent = (DomElement) e;
|
||||
depth = parent.depth + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The base URI of an Attr is always <code>null</code>.
|
||||
*/
|
||||
public final String getBaseURI()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shallow clone of the attribute, breaking all ties with any
|
||||
* elements.
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
DomAttr retval = (DomAttr) super.clone();
|
||||
retval.specified = true;
|
||||
return retval;
|
||||
}
|
||||
|
||||
private void mutating(String oldValue, String newValue, short why)
|
||||
{
|
||||
if (!reportMutations || parent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// EVENT: DOMAttrModified, target = parent,
|
||||
// prev/new values provided, also attr name
|
||||
MutationEvent event;
|
||||
|
||||
event = (MutationEvent) createEvent ("MutationEvents");
|
||||
event.initMutationEvent ("DOMAttrModified",
|
||||
true /* bubbles */, false /* nocancel */,
|
||||
null, oldValue, newValue, getNodeName (), why);
|
||||
parent.dispatchEvent (event);
|
||||
}
|
||||
|
||||
// DOM Level 3 methods
|
||||
|
||||
public TypeInfo getSchemaTypeInfo()
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
// DTD implementation
|
||||
DomDoctype doctype = (DomDoctype) parent.owner.getDoctype();
|
||||
if (doctype != null)
|
||||
{
|
||||
return doctype.getAttributeTypeInfo(parent.getNodeName(),
|
||||
getNodeName());
|
||||
}
|
||||
// TODO XML Schema implementation
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isId()
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
DomDoctype doctype = (DomDoctype) parent.owner.getDoctype();
|
||||
if (doctype != null)
|
||||
{
|
||||
DTDAttributeTypeInfo info =
|
||||
doctype.getAttributeTypeInfo(parent.getNodeName(),
|
||||
getNodeName());
|
||||
if (info != null && "ID".equals(info.type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
DomElement element = (DomElement) parent;
|
||||
if (element.userIdAttrs != null &&
|
||||
element.userIdAttrs.contains(this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// TODO XML Schema implementation
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/* DomCDATA.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.CDATASection;
|
||||
|
||||
/**
|
||||
* <p> "CDATASection" implementation.
|
||||
* This is a non-core DOM class, supporting the "XML" feature.
|
||||
* CDATA sections are just ways to represent text using different
|
||||
* delimeters. </p>
|
||||
*
|
||||
* <p> <em>You are strongly advised not to use CDATASection nodes.</em>
|
||||
* The advantage of having slightly prettier ways to print text that may
|
||||
* have lots of embedded XML delimiters, such as "&" and "<",
|
||||
* can be dwarfed by the cost of dealing with multiple kinds of text
|
||||
* nodes in all your algorithms. </p>
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomCDATA
|
||||
extends DomText
|
||||
implements CDATASection
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs a CDATA section node associated with the specified
|
||||
* document and holding the specified data.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a Document as part of
|
||||
* its createCDATASection functionality, or through a subclass which is
|
||||
* similarly used in a "Sub-DOM" style layer.
|
||||
*
|
||||
*/
|
||||
protected DomCDATA(DomDocument owner, String value)
|
||||
{
|
||||
super(CDATA_SECTION_NODE, owner, value);
|
||||
}
|
||||
|
||||
protected DomCDATA(DomDocument owner, char buf [], int off, int len)
|
||||
{
|
||||
super(CDATA_SECTION_NODE, owner, buf, off, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the string "#cdata-section".
|
||||
*/
|
||||
final public String getNodeName()
|
||||
{
|
||||
return "#cdata-section";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
/* DomCharacterData.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.CharacterData;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.events.MutationEvent;
|
||||
|
||||
|
||||
/**
|
||||
* <p> Abstract "CharacterData" implementation. This
|
||||
* facilitates reusing code in classes implementing subtypes of that DOM
|
||||
* interface (Text, Comment, CDATASection). </p>
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public abstract class DomCharacterData
|
||||
extends DomNode
|
||||
implements CharacterData
|
||||
{
|
||||
|
||||
private String text;
|
||||
|
||||
// package private
|
||||
DomCharacterData(short nodeType, DomDocument doc, String value)
|
||||
{
|
||||
super(nodeType, doc);
|
||||
text = (value == null) ? "" : value;
|
||||
}
|
||||
|
||||
// package private
|
||||
DomCharacterData(short nodeType, DomDocument doc,
|
||||
char[] buf, int offset, int length)
|
||||
{
|
||||
super(nodeType, doc);
|
||||
text = (buf == null) ? "" : new String(buf, offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Appends the specified data to the value of this node.
|
||||
* Causes a DOMCharacterDataModified mutation event to be reported.
|
||||
*/
|
||||
public void appendData(String arg)
|
||||
{
|
||||
if (isReadonly())
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
String value = text + arg;
|
||||
mutating(value);
|
||||
text = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Modifies the value of this node.
|
||||
* Causes a DOMCharacterDataModified mutation event to be reported.
|
||||
*/
|
||||
public void deleteData(int offset, int count)
|
||||
{
|
||||
if (isReadonly())
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
char[] raw = text.toCharArray();
|
||||
if (offset < 0 || count < 0 || offset > raw.length)
|
||||
{
|
||||
throw new DomEx(DomEx.INDEX_SIZE_ERR);
|
||||
}
|
||||
if ((offset + count) > raw.length)
|
||||
{
|
||||
count = raw.length - offset;
|
||||
}
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
char[] buf = new char[raw.length - count];
|
||||
System.arraycopy(raw, 0, buf, 0, offset);
|
||||
System.arraycopy(raw, offset + count, buf, offset,
|
||||
raw.length - (offset + count));
|
||||
String value = new String(buf);
|
||||
mutating(value);
|
||||
text = value;
|
||||
}
|
||||
catch (IndexOutOfBoundsException x)
|
||||
{
|
||||
throw new DomEx(DomEx.INDEX_SIZE_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the value of this node.
|
||||
*/
|
||||
public String getNodeValue()
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the value of this node; same as getNodeValue.
|
||||
*/
|
||||
public final String getData()
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the length of the data.
|
||||
*/
|
||||
public int getLength()
|
||||
{
|
||||
return text.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Modifies the value of this node.
|
||||
*/
|
||||
public void insertData(int offset, String arg)
|
||||
{
|
||||
if (isReadonly())
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
char[] raw = text.toCharArray();
|
||||
char[] tmp = arg.toCharArray ();
|
||||
char[] buf = new char[raw.length + tmp.length];
|
||||
|
||||
try
|
||||
{
|
||||
System.arraycopy(raw, 0, buf, 0, offset);
|
||||
System.arraycopy(tmp, 0, buf, offset, tmp.length);
|
||||
System.arraycopy(raw, offset, buf, offset + tmp.length,
|
||||
raw.length - offset);
|
||||
String value = new String(buf);
|
||||
mutating(value);
|
||||
text = value;
|
||||
}
|
||||
catch (IndexOutOfBoundsException x)
|
||||
{
|
||||
throw new DomEx(DomEx.INDEX_SIZE_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Modifies the value of this node. Causes DOMCharacterDataModified
|
||||
* mutation events to be reported (at least one).
|
||||
*/
|
||||
public void replaceData(int offset, int count, String arg)
|
||||
{
|
||||
if (readonly)
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
char[] raw = text.toCharArray();
|
||||
|
||||
// deleteData
|
||||
if (offset < 0 || count < 0 || offset > raw.length)
|
||||
{
|
||||
throw new DomEx(DomEx.INDEX_SIZE_ERR);
|
||||
}
|
||||
if ((offset + count) > raw.length)
|
||||
{
|
||||
count = raw.length - offset;
|
||||
}
|
||||
try
|
||||
{
|
||||
char[] buf = new char[raw.length - count];
|
||||
System.arraycopy(raw, 0, buf, 0, offset);
|
||||
System.arraycopy(raw, offset + count, buf, offset,
|
||||
raw.length - (offset + count));
|
||||
|
||||
// insertData
|
||||
char[] tmp = arg.toCharArray ();
|
||||
char[] buf2 = new char[buf.length + tmp.length];
|
||||
System.arraycopy(raw, 0, buf, 0, offset);
|
||||
System.arraycopy(tmp, 0, buf, offset, tmp.length);
|
||||
System.arraycopy(raw, offset, buf, offset + tmp.length,
|
||||
raw.length - offset);
|
||||
String value = new String(buf);
|
||||
mutating(value);
|
||||
text = value;
|
||||
}
|
||||
catch (IndexOutOfBoundsException x)
|
||||
{
|
||||
throw new DomEx(DomEx.INDEX_SIZE_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Assigns the value of this node.
|
||||
* Causes a DOMCharacterDataModified mutation event to be reported.
|
||||
*/
|
||||
public void setNodeValue(String value)
|
||||
{
|
||||
if (isReadonly())
|
||||
{
|
||||
throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
if (value == null)
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
mutating(value);
|
||||
text = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Assigns the value of this node; same as setNodeValue.
|
||||
*/
|
||||
final public void setData(String data)
|
||||
{
|
||||
setNodeValue(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the specified substring.
|
||||
*/
|
||||
public String substringData(int offset, int count)
|
||||
{
|
||||
try
|
||||
{
|
||||
return text.substring(offset, count);
|
||||
}
|
||||
catch (StringIndexOutOfBoundsException e)
|
||||
{
|
||||
if (offset >= 0 && count >= 0 && offset < text.length())
|
||||
{
|
||||
return text.substring(offset);
|
||||
}
|
||||
throw new DomEx(DomEx.INDEX_SIZE_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The base URI for character data is <code>null</code>.
|
||||
* @since DOM Level 3 Core
|
||||
*/
|
||||
public final String getBaseURI()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private void mutating(String newValue)
|
||||
{
|
||||
if (!reportMutations)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// EVENT: DOMCharacterDataModified, target = this,
|
||||
// prev/new values provided
|
||||
MutationEvent event;
|
||||
|
||||
event = (MutationEvent) createEvent("MutationEvents");
|
||||
event.initMutationEvent("DOMCharacterDataModified",
|
||||
true /* bubbles */, false /* nocancel */,
|
||||
null, text, newValue, null, (short) 0);
|
||||
dispatchEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/* DomComment.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.Comment;
|
||||
|
||||
/**
|
||||
* <p> "Comment" implementation.
|
||||
* Comments hold data intended for direct consumption by people;
|
||||
* programs should only use ProcessingInstruction nodes. Note that
|
||||
* since SAX makes comment reporting optional, XML systems that
|
||||
* rely on comments (such as by using this class) will often lose
|
||||
* those comments at some point in the processing pipeline. </p>
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomComment
|
||||
extends DomCharacterData
|
||||
implements Comment
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs a comment node associated with the specified
|
||||
* document and holding the specified data.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a Document as part of
|
||||
* its createComment functionality, or through a subclass which is
|
||||
* similarly used in a "Sub-DOM" style layer.
|
||||
*/
|
||||
protected DomComment(DomDocument owner, String value)
|
||||
{
|
||||
super(COMMENT_NODE, owner, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the string "#comment".
|
||||
*/
|
||||
final public String getNodeName()
|
||||
{
|
||||
return "#comment";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,454 @@
|
||||
/* DomDoctype.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.HashMap;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.Entity;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Notation;
|
||||
|
||||
/**
|
||||
* <p> "DocumentType" implementation (with no extensions for supporting
|
||||
* any document typing information). This is a non-core DOM class,
|
||||
* supporting the "XML" feature. </p>
|
||||
*
|
||||
* <p> <em>Few XML applications will actually care about this partial
|
||||
* DTD support</em>, since it doesn't expose any (!) of the data typing
|
||||
* facilities which can motivate applications to use DTDs. It does not
|
||||
* expose element content models, or information about attribute typing
|
||||
* rules. Plus the information it exposes isn't very useful; as one example,
|
||||
* DOM exposes information about unparsed ENTITY objects, which is only used
|
||||
* with certain element attributes, but does not expose the information about
|
||||
* those attributes which is needed to apply that data! </p>
|
||||
*
|
||||
* <p> Also, note that there are no nonportable ways to associate even the
|
||||
* notation and entity information exposed by DOM with a DocumentType. While
|
||||
* there is a DOM L2 method to construct a DocumentType, it only gives access
|
||||
* to the textual content of the <!DOCTYPE ...> declaration. </p>
|
||||
*
|
||||
* <p> In short, <em>you are strongly advised not to rely on this incomplete
|
||||
* DTD functionality</em> in your application code.</p>
|
||||
*
|
||||
* @see DomEntity
|
||||
* @see DomEntityReference
|
||||
* @see DomNotation
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomDoctype
|
||||
extends DomExtern
|
||||
implements DocumentType
|
||||
{
|
||||
|
||||
private DomNamedNodeMap notations;
|
||||
private DomNamedNodeMap entities;
|
||||
private final DOMImplementation implementation;
|
||||
private String subset;
|
||||
|
||||
private HashMap elements = new HashMap();
|
||||
private boolean ids;
|
||||
|
||||
/**
|
||||
* Constructs a DocumentType node associated with the specified
|
||||
* implementation, with the specified name.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a DOMImplementation as
|
||||
* part of its createDocumentType functionality, or through a subclass
|
||||
* which is similarly used in a "Sub-DOM" style layer.
|
||||
*
|
||||
* <p> Note that at this time there is no standard SAX API granting
|
||||
* access to the internal subset text, so that relying on that value
|
||||
* is not currently portable.
|
||||
*
|
||||
* @param impl The implementation with which this object is associated
|
||||
* @param name Name of this root element
|
||||
* @param publicId If non-null, provides the external subset's
|
||||
* PUBLIC identifier
|
||||
* @param systemId If non-null, provides the external subset's
|
||||
* SYSTEM identifier
|
||||
* @param internalSubset Provides the literal value (unparsed, no
|
||||
* entities expanded) of the DTD's internal subset.
|
||||
*/
|
||||
protected DomDoctype(DOMImplementation impl,
|
||||
String name,
|
||||
String publicId,
|
||||
String systemId,
|
||||
String internalSubset)
|
||||
{
|
||||
super(DOCUMENT_TYPE_NODE, null, name, publicId, systemId);
|
||||
implementation = impl;
|
||||
subset = internalSubset;
|
||||
}
|
||||
|
||||
/**
|
||||
* JAXP builder constructor.
|
||||
* @param doc the document
|
||||
* @param name the name of the document element
|
||||
* @param publicId the public ID of the document type declaration
|
||||
* @param systemId the system ID of the document type declaration
|
||||
*/
|
||||
public DomDoctype(DomDocument doc,
|
||||
String name,
|
||||
String publicId,
|
||||
String systemId)
|
||||
{
|
||||
super(DOCUMENT_TYPE_NODE, doc, name, publicId, systemId);
|
||||
implementation = doc.getImplementation();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the root element's name (just like getNodeName).
|
||||
*/
|
||||
final public String getName()
|
||||
{
|
||||
return getNodeName();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns information about any general entities declared
|
||||
* in the DTD.
|
||||
*
|
||||
* <p><em>Note: DOM L1 doesn't throw a DOMException here, but
|
||||
* then it doesn't have the strange construction rules of L2.</em>
|
||||
*
|
||||
* @exception DOMException HIERARCHY_REQUEST_ERR if the DocumentType
|
||||
* is not associated with a document.
|
||||
*/
|
||||
public NamedNodeMap getEntities()
|
||||
{
|
||||
if (entities == null)
|
||||
{
|
||||
entities = new DomNamedNodeMap(this, Node.ENTITY_NODE);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the declaration of a general entity in this DocumentType.
|
||||
*
|
||||
* @param name Name of the entity
|
||||
* @param publicId If non-null, provides the entity's PUBLIC identifier
|
||||
* @param systemId Provides the entity's SYSTEM identifier
|
||||
* @param notation If non-null, provides the entity's notation
|
||||
* (indicating an unparsed entity)
|
||||
* @return The Entity that was declared, or null if the entity wasn't
|
||||
* recorded (because it's a parameter entity or because an entity with
|
||||
* this name was already declared).
|
||||
*
|
||||
* @exception DOMException NO_MODIFICATION_ALLOWED_ERR if the
|
||||
* DocumentType is no longer writable.
|
||||
* @exception DOMException HIERARCHY_REQUEST_ERR if the DocumentType
|
||||
* is not associated with a document.
|
||||
*/
|
||||
public Entity declareEntity(String name,
|
||||
String publicId,
|
||||
String systemId,
|
||||
String notation)
|
||||
{
|
||||
DomEntity entity;
|
||||
|
||||
if (name.charAt(0) == '%' || "[dtd]".equals(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (isReadonly())
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
getEntities();
|
||||
|
||||
DomDocument.checkName(name, (owner != null) ?
|
||||
"1.1".equals(owner.getXmlVersion()) : false);
|
||||
if (entities.getNamedItem(name) != null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
entity = new DomEntity(owner, name, publicId, systemId, notation);
|
||||
entities.setNamedItem(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns information about any notations declared in the DTD.
|
||||
*
|
||||
* <p><em>Note: DOM L1 doesn't throw a DOMException here, but
|
||||
* then it doesn't have the strange construction rules of L2.</em>
|
||||
*
|
||||
* @exception DOMException HIERARCHY_REQUEST_ERR if the DocumentType
|
||||
* is not associated with a document.
|
||||
*/
|
||||
public NamedNodeMap getNotations()
|
||||
{
|
||||
if (notations == null)
|
||||
{
|
||||
notations = new DomNamedNodeMap(this, Node.NOTATION_NODE);
|
||||
}
|
||||
return notations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the declaration of a notation in this DocumentType.
|
||||
*
|
||||
* @param name Name of the notation
|
||||
* @param publicId If non-null, provides the notation's PUBLIC identifier
|
||||
* @param systemId If non-null, provides the notation's SYSTEM identifier
|
||||
* @return The notation that was declared.
|
||||
*
|
||||
* @exception DOMException NO_MODIFICATION_ALLOWED_ERR if the
|
||||
* DocumentType is no longer writable.
|
||||
* @exception DOMException HIERARCHY_REQUEST_ERR if the DocumentType
|
||||
* is not associated with a document.
|
||||
*/
|
||||
public Notation declareNotation(String name,
|
||||
String publicId,
|
||||
String systemId)
|
||||
{
|
||||
DomNotation notation;
|
||||
|
||||
if (isReadonly())
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
getNotations();
|
||||
|
||||
DomDocument.checkName(name, (owner != null) ?
|
||||
"1.1".equals(owner.getXmlVersion()) : false);
|
||||
|
||||
notation = new DomNotation(owner, name, publicId, systemId);
|
||||
notations.setNamedItem(notation);
|
||||
return notation;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the internal subset of the document, as a string of unparsed
|
||||
* XML declarations (and comments, PIs, whitespace); or returns null if
|
||||
* there is no such subset. There is no vendor-independent expectation
|
||||
* that this attribute be set, or that declarations found in it be
|
||||
* reflected in the <em>entities</em> or <em>notations</em> attributes
|
||||
* of this Document "Type" object.
|
||||
*
|
||||
* <p> Some application-specific XML profiles require that documents
|
||||
* only use specific PUBLIC identifiers, without an internal subset
|
||||
* to modify the interperetation of the declarations associated with
|
||||
* that PUBLIC identifier through some standard.
|
||||
*/
|
||||
public String getInternalSubset()
|
||||
{
|
||||
return subset;
|
||||
}
|
||||
|
||||
/**
|
||||
* The base URI of a DocumentType is always <code>null</code>.
|
||||
* See the Infoset Mapping, appendix C.
|
||||
*/
|
||||
public final String getBaseURI()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal "readonly" flag so the node and its associated
|
||||
* data (only lists of entities and notations, no type information
|
||||
* at the moment) can't be changed.
|
||||
*/
|
||||
public void makeReadonly()
|
||||
{
|
||||
super.makeReadonly();
|
||||
if (entities != null)
|
||||
{
|
||||
entities.makeReadonly();
|
||||
}
|
||||
if (notations != null)
|
||||
{
|
||||
notations.makeReadonly();
|
||||
}
|
||||
}
|
||||
|
||||
void setOwner(DomDocument doc)
|
||||
{
|
||||
if (entities != null)
|
||||
{
|
||||
for (DomNode ctx = entities.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
ctx.setOwner(doc);
|
||||
}
|
||||
}
|
||||
if (notations != null)
|
||||
{
|
||||
for (DomNode ctx = notations.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
ctx.setOwner(doc);
|
||||
}
|
||||
}
|
||||
super.setOwner(doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Consults the DOM implementation to determine if the requested
|
||||
* feature is supported.
|
||||
*/
|
||||
final public boolean supports(String feature, String version)
|
||||
{
|
||||
return implementation.hasFeature(feature, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the implementation associated with this document type.
|
||||
*/
|
||||
final public DOMImplementation getImplementation()
|
||||
{
|
||||
return implementation;
|
||||
}
|
||||
|
||||
public void elementDecl(String name, String model)
|
||||
{
|
||||
DTDElementTypeInfo info = getElementTypeInfo(name);
|
||||
if (info == null)
|
||||
{
|
||||
info = new DTDElementTypeInfo(name, model);
|
||||
elements.put(name, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.model = model;
|
||||
}
|
||||
}
|
||||
|
||||
DTDElementTypeInfo getElementTypeInfo(String name)
|
||||
{
|
||||
return (DTDElementTypeInfo) elements.get(name);
|
||||
}
|
||||
|
||||
public void attributeDecl(String eName, String aName, String type,
|
||||
String mode, String value)
|
||||
{
|
||||
DTDAttributeTypeInfo info = new DTDAttributeTypeInfo(eName, aName, type,
|
||||
mode, value);
|
||||
DTDElementTypeInfo elementInfo = getElementTypeInfo(eName);
|
||||
if (elementInfo == null)
|
||||
{
|
||||
elementInfo = new DTDElementTypeInfo(eName, null);
|
||||
elements.put(eName, elementInfo);
|
||||
}
|
||||
elementInfo.setAttributeTypeInfo(aName, info);
|
||||
if ("ID".equals(type))
|
||||
{
|
||||
ids = true;
|
||||
}
|
||||
}
|
||||
|
||||
DTDAttributeTypeInfo getAttributeTypeInfo(String elementName, String name)
|
||||
{
|
||||
DTDElementTypeInfo elementInfo =
|
||||
(DTDElementTypeInfo) elements.get(elementName);
|
||||
return (elementInfo == null) ? null :
|
||||
elementInfo.getAttributeTypeInfo(name);
|
||||
}
|
||||
|
||||
boolean hasIds()
|
||||
{
|
||||
return ids;
|
||||
}
|
||||
|
||||
public boolean isSameNode(Node arg)
|
||||
{
|
||||
if (equals(arg))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(arg instanceof DocumentType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DocumentType doctype = (DocumentType) arg;
|
||||
if (!equal(getPublicId(), doctype.getPublicId()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!equal(getSystemId(), doctype.getSystemId()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!equal(getInternalSubset(), doctype.getInternalSubset()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// TODO entities
|
||||
// TODO notations
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shallow clone of the doctype, except that associated
|
||||
* entities and notations are (deep) cloned.
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
DomDoctype node = (DomDoctype) super.clone();
|
||||
|
||||
if (entities != null)
|
||||
{
|
||||
node.entities = new DomNamedNodeMap(node, Node.ENTITY_NODE);
|
||||
for (DomNode ctx = entities.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
node.entities.setNamedItem(ctx.cloneNode(true));
|
||||
}
|
||||
}
|
||||
if (notations != null)
|
||||
{
|
||||
node.notations = new DomNamedNodeMap(node, Node.NOTATION_NODE);
|
||||
for (DomNode ctx = notations.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
node.notations.setNamedItem(ctx.cloneNode(true));
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
/* DomDocumentBuilder.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DOMConfiguration;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.ls.DOMImplementationLS;
|
||||
import org.w3c.dom.ls.LSInput;
|
||||
import org.w3c.dom.ls.LSParser;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Document builder using the GNU DOM Load & Save implementation.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DomDocumentBuilder
|
||||
extends DocumentBuilder
|
||||
{
|
||||
|
||||
final DOMImplementation impl;
|
||||
final DOMImplementationLS ls;
|
||||
final LSParser parser;
|
||||
|
||||
DomDocumentBuilder(DOMImplementation impl,
|
||||
DOMImplementationLS ls,
|
||||
LSParser parser)
|
||||
{
|
||||
this.impl = impl;
|
||||
this.ls = ls;
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
public boolean isNamespaceAware()
|
||||
{
|
||||
DOMConfiguration config = parser.getDomConfig();
|
||||
return ((Boolean) config.getParameter("namespaces")).booleanValue();
|
||||
}
|
||||
|
||||
public boolean isValidating()
|
||||
{
|
||||
DOMConfiguration config = parser.getDomConfig();
|
||||
return ((Boolean) config.getParameter("validating")).booleanValue();
|
||||
}
|
||||
|
||||
public boolean isXIncludeAware()
|
||||
{
|
||||
DOMConfiguration config = parser.getDomConfig();
|
||||
return ((Boolean) config.getParameter("xinclude-aware")).booleanValue();
|
||||
}
|
||||
|
||||
public void setEntityResolver(EntityResolver resolver)
|
||||
{
|
||||
DOMConfiguration config = parser.getDomConfig();
|
||||
config.setParameter("entity-resolver", resolver);
|
||||
}
|
||||
|
||||
public void setErrorHandler(ErrorHandler handler)
|
||||
{
|
||||
DOMConfiguration config = parser.getDomConfig();
|
||||
config.setParameter("error-handler", handler);
|
||||
}
|
||||
|
||||
public DOMImplementation getDOMImplementation()
|
||||
{
|
||||
return impl;
|
||||
}
|
||||
|
||||
public Document newDocument()
|
||||
{
|
||||
return impl.createDocument(null, null, null);
|
||||
}
|
||||
|
||||
public Document parse(InputStream in)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
LSInput input = ls.createLSInput();
|
||||
input.setByteStream(in);
|
||||
return parser.parse(input);
|
||||
}
|
||||
|
||||
public Document parse(InputStream in, String systemId)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
LSInput input = ls.createLSInput();
|
||||
input.setByteStream(in);
|
||||
input.setSystemId(systemId);
|
||||
return parser.parse(input);
|
||||
}
|
||||
|
||||
public Document parse(String systemId)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
return parser.parseURI(systemId);
|
||||
}
|
||||
|
||||
public Document parse(InputSource is)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
LSInput input = ls.createLSInput();
|
||||
InputStream in = is.getByteStream();
|
||||
if (in != null)
|
||||
{
|
||||
input.setByteStream(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
input.setCharacterStream(is.getCharacterStream());
|
||||
}
|
||||
input.setPublicId(is.getPublicId());
|
||||
input.setSystemId(is.getSystemId());
|
||||
input.setEncoding(is.getEncoding());
|
||||
return parser.parse(input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/* DomDocumentBuilderFactory.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.FactoryConfigurationError;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.w3c.dom.DOMConfiguration;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
|
||||
import org.w3c.dom.ls.DOMImplementationLS;
|
||||
import org.w3c.dom.ls.LSParser;
|
||||
|
||||
/**
|
||||
* Document builder factory that uses a DOM Level 3 Load & Save
|
||||
* implementation.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomDocumentBuilderFactory
|
||||
extends DocumentBuilderFactory
|
||||
{
|
||||
|
||||
final DOMImplementation impl;
|
||||
final DOMImplementationLS ls;
|
||||
|
||||
public DomDocumentBuilderFactory()
|
||||
{
|
||||
try
|
||||
{
|
||||
DOMImplementationRegistry reg =
|
||||
DOMImplementationRegistry.newInstance();
|
||||
impl = reg.getDOMImplementation("LS 3.0");
|
||||
if (impl == null)
|
||||
{
|
||||
throw new FactoryConfigurationError("no LS implementations found");
|
||||
}
|
||||
ls = (DOMImplementationLS) impl;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new FactoryConfigurationError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public DocumentBuilder newDocumentBuilder()
|
||||
throws ParserConfigurationException
|
||||
{
|
||||
LSParser parser = ls.createLSParser(DOMImplementationLS.MODE_ASYNCHRONOUS,
|
||||
"http://www.w3.org/TR/REC-xml");
|
||||
DOMConfiguration config = parser.getDomConfig();
|
||||
setParameter(config, "namespaces",
|
||||
isNamespaceAware() ? Boolean.TRUE : Boolean.FALSE);
|
||||
setParameter(config, "element-content-whitespace",
|
||||
isIgnoringElementContentWhitespace() ? Boolean.FALSE :
|
||||
Boolean.TRUE);
|
||||
setParameter(config, "comments",
|
||||
isIgnoringComments() ? Boolean.FALSE : Boolean.TRUE);
|
||||
setParameter(config, "expand-entity-references",
|
||||
isExpandEntityReferences() ? Boolean.TRUE : Boolean.FALSE);
|
||||
setParameter(config, "coalescing",
|
||||
isCoalescing() ? Boolean.TRUE : Boolean.FALSE);
|
||||
setParameter(config, "validating",
|
||||
isValidating() ? Boolean.TRUE : Boolean.FALSE);
|
||||
setParameter(config, "xinclude-aware",
|
||||
isXIncludeAware() ? Boolean.TRUE : Boolean.FALSE);
|
||||
return new DomDocumentBuilder(impl, ls, parser);
|
||||
}
|
||||
|
||||
void setParameter(DOMConfiguration config, String name, Object value)
|
||||
throws ParserConfigurationException
|
||||
{
|
||||
if (!config.canSetParameter(name, value))
|
||||
{
|
||||
throw new ParserConfigurationException(name);
|
||||
}
|
||||
config.setParameter(name, value);
|
||||
}
|
||||
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setAttribute(String name, Object value)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
/* DomDocumentConfiguration.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.w3c.dom.DOMConfiguration;
|
||||
import org.w3c.dom.DOMErrorHandler;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.DOMStringList;
|
||||
|
||||
/**
|
||||
* Document configuration, used to store normalization and other parameters.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DomDocumentConfiguration
|
||||
implements DOMConfiguration, DOMStringList
|
||||
{
|
||||
|
||||
private static final List SUPPORTED_PARAMETERS =
|
||||
Arrays.asList(new String[] { "cdata-sections",
|
||||
"comments",
|
||||
"element-content-whitespace",
|
||||
"entities",
|
||||
"error-handler",
|
||||
"namespace-declarations",
|
||||
"split-cdata-sections",
|
||||
"infoset"});
|
||||
|
||||
boolean cdataSections = true;
|
||||
boolean comments = true;
|
||||
boolean elementContentWhitespace = true;
|
||||
boolean entities = true;
|
||||
DOMErrorHandler errorHandler;
|
||||
boolean namespaceDeclarations = true;
|
||||
boolean splitCdataSections = true;
|
||||
|
||||
public void setParameter(String name, Object value)
|
||||
throws DOMException
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
if ("cdata-sections".equals(name))
|
||||
{
|
||||
cdataSections = "true".equals(value.toString());
|
||||
}
|
||||
else if ("comments".equals(name))
|
||||
{
|
||||
comments = "true".equals(value.toString());
|
||||
}
|
||||
else if ("element-content-whitespace".equals(name))
|
||||
{
|
||||
elementContentWhitespace = "true".equals(value.toString());
|
||||
}
|
||||
else if ("entities".equals(name))
|
||||
{
|
||||
entities = "true".equals(value.toString());
|
||||
}
|
||||
else if ("error-handler".equals(name))
|
||||
{
|
||||
try
|
||||
{
|
||||
errorHandler = (DOMErrorHandler) value;
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
throw new DomEx(DomEx.TYPE_MISMATCH_ERR,
|
||||
value.getClass().getName(), null, 0);
|
||||
}
|
||||
}
|
||||
else if ("namespace-declarations".equals(name))
|
||||
{
|
||||
namespaceDeclarations = "true".equals(value.toString());
|
||||
}
|
||||
else if ("split-cdata-sections".equals(name))
|
||||
{
|
||||
comments = "true".equals(value.toString());
|
||||
}
|
||||
else if ("infoset".equals(name))
|
||||
{
|
||||
if ("true".equals(value.toString()))
|
||||
{
|
||||
entities = false;
|
||||
cdataSections = false;
|
||||
namespaceDeclarations = true;
|
||||
elementContentWhitespace = true;
|
||||
comments = true;
|
||||
}
|
||||
}
|
||||
else if (("canonical-form".equals(name) ||
|
||||
"check-character-normalization".equals(name) ||
|
||||
"datatype-normalization".equals(name) ||
|
||||
"normalize-characters".equals(name) ||
|
||||
"validate".equals(name) ||
|
||||
"validate-if-schema".equals(name)) &&
|
||||
"false".equals(value.toString()))
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
else if (("namespaces".equals(name) ||
|
||||
"well-formed".equals(name)) &&
|
||||
"true".equals(value.toString()))
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_SUPPORTED_ERR, name, null, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getParameter(String name)
|
||||
throws DOMException
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
if ("cdata-sections".equals(name))
|
||||
{
|
||||
return cdataSections ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("comments".equals(name))
|
||||
{
|
||||
return comments ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("element-content-whitespace".equals(name))
|
||||
{
|
||||
return elementContentWhitespace ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("entities".equals(name))
|
||||
{
|
||||
return entities ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("error-handler".equals(name))
|
||||
{
|
||||
return errorHandler;
|
||||
}
|
||||
else if ("namespace-declarations".equals(name))
|
||||
{
|
||||
return namespaceDeclarations ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("split-cdata-sections".equals(name))
|
||||
{
|
||||
return comments ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("canonical-form".equals(name) ||
|
||||
"check-character-normalization".equals(name) ||
|
||||
"datatype-normalization".equals(name) ||
|
||||
"normalize-characters".equals(name) ||
|
||||
"validate".equals(name) ||
|
||||
"validate-if-schema".equals(name))
|
||||
{
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
else if ("namespaces".equals(name) ||
|
||||
"well-formed".equals(name))
|
||||
{
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
else if ("infoset".equals(name))
|
||||
{
|
||||
return (entities == false &&
|
||||
cdataSections == false &&
|
||||
namespaceDeclarations == true &&
|
||||
comments == true) ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
throw new DomEx(DomEx.NOT_SUPPORTED_ERR, name, null, 0);
|
||||
}
|
||||
|
||||
public boolean canSetParameter(String name, Object value)
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
if ("error-handler".equals(name))
|
||||
{
|
||||
return (value == null || value instanceof DOMErrorHandler);
|
||||
}
|
||||
else if (contains(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if ("canonical-form".equals(name) ||
|
||||
"check-character-normalization".equals(name) ||
|
||||
"datatype-normalization".equals(name) ||
|
||||
"normalize-characters".equals(name) ||
|
||||
"validate".equals(name) ||
|
||||
"validate-if-schema".equals(name))
|
||||
{
|
||||
return "false".equals(value.toString());
|
||||
}
|
||||
else if ("namespaces".equals(name) ||
|
||||
"well-formed".equals(name))
|
||||
{
|
||||
return "true".equals(value.toString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public DOMStringList getParameterNames()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public String item(int i)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (String) SUPPORTED_PARAMETERS.get(i);
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
return SUPPORTED_PARAMETERS.size();
|
||||
}
|
||||
|
||||
public boolean contains(String str)
|
||||
{
|
||||
str = str.toLowerCase();
|
||||
return SUPPORTED_PARAMETERS.contains(str);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
/* DomElement.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.xml.XMLConstants;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.TypeInfo;
|
||||
|
||||
/**
|
||||
* <p> "Element" implementation.
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomElement
|
||||
extends DomNsNode
|
||||
implements Element
|
||||
{
|
||||
|
||||
/**
|
||||
* User-defined ID attributes.
|
||||
* Used by DomAttr.isId and DomDocument.getElementById
|
||||
*/
|
||||
Set userIdAttrs;
|
||||
|
||||
// Attributes are VERY expensive in DOM, and not just for
|
||||
// this implementation. Avoid creating them.
|
||||
private DomNamedNodeMap attributes;
|
||||
|
||||
// xml:space cache
|
||||
String xmlSpace = "";
|
||||
|
||||
/**
|
||||
* Constructs an Element node associated with the specified document.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a Document as part
|
||||
* of its createElement functionality, or through a subclass which is
|
||||
* similarly used in a "Sub-DOM" style layer.
|
||||
*
|
||||
* @param owner The document with which this node is associated
|
||||
* @param namespaceURI Combined with the local part of the name,
|
||||
* this is used to uniquely identify a type of element
|
||||
* @param name Name of this element, which may include a prefix
|
||||
*/
|
||||
protected DomElement(DomDocument owner, String namespaceURI, String name)
|
||||
{
|
||||
super(ELEMENT_NODE, owner, namespaceURI, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the element's attributes
|
||||
*/
|
||||
public NamedNodeMap getAttributes()
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
attributes = new DomNamedNodeMap(this, Node.ATTRIBUTE_NODE);
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2></b>
|
||||
* Returns true iff this is an element node with attributes.
|
||||
*/
|
||||
public boolean hasAttributes()
|
||||
{
|
||||
return attributes != null && attributes.length != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shallow clone of the element, except that associated
|
||||
* attributes are (deep) cloned.
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
DomElement node = (DomElement) super.clone();
|
||||
|
||||
if (attributes != null)
|
||||
{
|
||||
node.attributes = new DomNamedNodeMap(node, Node.ATTRIBUTE_NODE);
|
||||
for (DomNode ctx = attributes.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
node.attributes.setNamedItemNS(ctx.cloneNode(true));
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
void setOwner(DomDocument doc)
|
||||
{
|
||||
if (attributes != null)
|
||||
{
|
||||
for (DomNode ctx = attributes.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
ctx.setOwner(doc);
|
||||
}
|
||||
}
|
||||
super.setOwner(doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this element, its children, and its associated attributes as
|
||||
* readonly.
|
||||
*/
|
||||
public void makeReadonly()
|
||||
{
|
||||
super.makeReadonly();
|
||||
if (attributes != null)
|
||||
{
|
||||
attributes.makeReadonly();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the element name (same as getNodeName).
|
||||
*/
|
||||
final public String getTagName()
|
||||
{
|
||||
return getNodeName();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the value of the specified attribute, or an
|
||||
* empty string.
|
||||
*/
|
||||
public String getAttribute(String name)
|
||||
{
|
||||
if ("xml:space" == name) // NB only works on interned string
|
||||
{
|
||||
// Use cached value
|
||||
return xmlSpace;
|
||||
}
|
||||
Attr attr = getAttributeNode(name);
|
||||
return (attr == null) ? "" : attr.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns true if the element has an attribute with the
|
||||
* specified name (specified or DTD defaulted).
|
||||
*/
|
||||
public boolean hasAttribute(String name)
|
||||
{
|
||||
return getAttributeNode(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns true if the element has an attribute with the
|
||||
* specified name (specified or DTD defaulted).
|
||||
*/
|
||||
public boolean hasAttributeNS(String namespaceURI, String local)
|
||||
{
|
||||
return getAttributeNodeNS(namespaceURI, local) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the value of the specified attribute, or an
|
||||
* empty string.
|
||||
*/
|
||||
public String getAttributeNS(String namespaceURI, String local)
|
||||
{
|
||||
Attr attr = getAttributeNodeNS(namespaceURI, local);
|
||||
return (attr == null) ? "" : attr.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the appropriate attribute node; the name is the
|
||||
* nodeName property of the attribute.
|
||||
*/
|
||||
public Attr getAttributeNode(String name)
|
||||
{
|
||||
return (attributes == null) ? null :
|
||||
(Attr) attributes.getNamedItem(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the appropriate attribute node; the name combines
|
||||
* the namespace name and the local part.
|
||||
*/
|
||||
public Attr getAttributeNodeNS(String namespace, String localPart)
|
||||
{
|
||||
return (attributes == null) ? null :
|
||||
(Attr) attributes.getNamedItemNS(namespace, localPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Modifies an existing attribute to have the specified value,
|
||||
* or creates a new one with that value. The name used is the
|
||||
* nodeName value.
|
||||
*/
|
||||
public void setAttribute(String name, String value)
|
||||
{
|
||||
Attr attr = getAttributeNode(name);
|
||||
if (attr != null)
|
||||
{
|
||||
attr.setNodeValue(value);
|
||||
((DomAttr) attr).setSpecified(true);
|
||||
return;
|
||||
}
|
||||
attr = owner.createAttribute(name);
|
||||
attr.setNodeValue(value);
|
||||
setAttributeNode(attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Modifies an existing attribute to have the specified value,
|
||||
* or creates a new one with that value.
|
||||
*/
|
||||
public void setAttributeNS(String uri, String aname, String value)
|
||||
{
|
||||
if (("xmlns".equals (aname) || aname.startsWith ("xmlns:"))
|
||||
&& !XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals (uri))
|
||||
{
|
||||
throw new DomEx(DomEx.NAMESPACE_ERR,
|
||||
"setting xmlns attribute to illegal value", this, 0);
|
||||
}
|
||||
|
||||
Attr attr = getAttributeNodeNS(uri, aname);
|
||||
if (attr != null)
|
||||
{
|
||||
attr.setNodeValue(value);
|
||||
return;
|
||||
}
|
||||
attr = owner.createAttributeNS(uri, aname);
|
||||
attr.setNodeValue(value);
|
||||
setAttributeNodeNS(attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Stores the specified attribute, optionally overwriting any
|
||||
* existing one with that name.
|
||||
*/
|
||||
public Attr setAttributeNode(Attr attr)
|
||||
{
|
||||
return (Attr) getAttributes().setNamedItem(attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Stores the specified attribute, optionally overwriting any
|
||||
* existing one with that name.
|
||||
*/
|
||||
public Attr setAttributeNodeNS(Attr attr)
|
||||
{
|
||||
return (Attr) getAttributes().setNamedItemNS(attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Removes the appropriate attribute node.
|
||||
* If there is no such node, this is (bizarrely enough) a NOP so you
|
||||
* won't see exceptions if your code deletes non-existent attributes.
|
||||
*
|
||||
* <p>Note that since there is no portable way for DOM to record
|
||||
* DTD information, default values for attributes will never be
|
||||
* provided automatically.
|
||||
*/
|
||||
public void removeAttribute(String name)
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
attributes.removeNamedItem(name);
|
||||
}
|
||||
catch (DomEx e)
|
||||
{
|
||||
if (e.code != DomEx.NOT_FOUND_ERR)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Removes the appropriate attribute node; the name is the
|
||||
* nodeName property of the attribute.
|
||||
*
|
||||
* <p>Note that since there is no portable way for DOM to record
|
||||
* DTD information, default values for attributes will never be
|
||||
* provided automatically.
|
||||
*/
|
||||
public Attr removeAttributeNode(Attr node)
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_FOUND_ERR, null, node, 0);
|
||||
}
|
||||
return (Attr) attributes.removeNamedItem(node.getNodeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Removes the appropriate attribute node; the name combines
|
||||
* the namespace name and the local part.
|
||||
*
|
||||
* <p>Note that since there is no portable way for DOM to record
|
||||
* DTD information, default values for attributes will never be
|
||||
* provided automatically.
|
||||
*/
|
||||
public void removeAttributeNS(String namespace, String localPart)
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_FOUND_ERR, localPart, null, 0);
|
||||
}
|
||||
attributes.removeNamedItemNS (namespace, localPart);
|
||||
}
|
||||
|
||||
// DOM Level 3 methods
|
||||
|
||||
public String lookupPrefix(String namespaceURI)
|
||||
{
|
||||
if (namespaceURI == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String namespace = getNamespaceURI();
|
||||
if (namespace != null && namespace.equals(namespaceURI))
|
||||
{
|
||||
return getPrefix();
|
||||
}
|
||||
if (attributes != null)
|
||||
{
|
||||
for (DomNode ctx = attributes.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI
|
||||
.equals(ctx.getNamespaceURI()))
|
||||
{
|
||||
String value = ctx.getNodeValue();
|
||||
if (value.equals(namespaceURI))
|
||||
{
|
||||
return ctx.getLocalName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.lookupPrefix(namespaceURI);
|
||||
}
|
||||
|
||||
public boolean isDefaultNamespace(String namespaceURI)
|
||||
{
|
||||
String namespace = getNamespaceURI();
|
||||
if (namespace != null && namespace.equals(namespaceURI))
|
||||
{
|
||||
return getPrefix() == null;
|
||||
}
|
||||
if (attributes != null)
|
||||
{
|
||||
for (DomNode ctx = attributes.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI
|
||||
.equals(ctx.getNamespaceURI()))
|
||||
{
|
||||
String qName = ctx.getNodeName();
|
||||
return (XMLConstants.XMLNS_ATTRIBUTE.equals(qName));
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.isDefaultNamespace(namespaceURI);
|
||||
}
|
||||
|
||||
public String lookupNamespaceURI(String prefix)
|
||||
{
|
||||
String namespace = getNamespaceURI();
|
||||
if (namespace != null && equal(prefix, getPrefix()))
|
||||
{
|
||||
return namespace;
|
||||
}
|
||||
if (attributes != null)
|
||||
{
|
||||
for (DomNode ctx = attributes.first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI
|
||||
.equals(ctx.getNamespaceURI()))
|
||||
{
|
||||
if (prefix == null)
|
||||
{
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE.equals(ctx.getNodeName()))
|
||||
{
|
||||
return ctx.getNodeValue();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prefix.equals(ctx.getLocalName()))
|
||||
{
|
||||
return ctx.getNodeValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.lookupNamespaceURI(prefix);
|
||||
}
|
||||
|
||||
public String getBaseURI()
|
||||
{
|
||||
if (attributes != null)
|
||||
{
|
||||
Node xmlBase =
|
||||
attributes.getNamedItemNS(XMLConstants.XML_NS_URI, "base");
|
||||
if (xmlBase != null)
|
||||
{
|
||||
return xmlBase.getNodeValue();
|
||||
}
|
||||
}
|
||||
return super.getBaseURI();
|
||||
}
|
||||
|
||||
public TypeInfo getSchemaTypeInfo()
|
||||
{
|
||||
// DTD implementation
|
||||
DomDoctype doctype = (DomDoctype) owner.getDoctype();
|
||||
if (doctype != null)
|
||||
{
|
||||
return doctype.getElementTypeInfo(getNodeName());
|
||||
}
|
||||
// TODO XML Schema implementation
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setIdAttribute(String name, boolean isId)
|
||||
{
|
||||
NamedNodeMap attrs = getAttributes();
|
||||
Attr attr = (Attr) attrs.getNamedItem(name);
|
||||
setIdAttributeNode(attr, isId);
|
||||
}
|
||||
|
||||
public void setIdAttributeNode(Attr attr, boolean isId)
|
||||
{
|
||||
if (readonly)
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
if (attr == null || attr.getOwnerElement() != this)
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_FOUND_ERR);
|
||||
}
|
||||
if (isId)
|
||||
{
|
||||
if (userIdAttrs == null)
|
||||
{
|
||||
userIdAttrs = new HashSet();
|
||||
}
|
||||
userIdAttrs.add(attr);
|
||||
}
|
||||
else if (userIdAttrs != null)
|
||||
{
|
||||
userIdAttrs.remove(attr);
|
||||
if (userIdAttrs.isEmpty())
|
||||
{
|
||||
userIdAttrs = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setIdAttributeNS(String namespaceURI, String localName,
|
||||
boolean isId)
|
||||
{
|
||||
NamedNodeMap attrs = getAttributes();
|
||||
Attr attr = (Attr) attrs.getNamedItemNS(namespaceURI, localName);
|
||||
setIdAttributeNode(attr, isId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/* DomEntity.java --
|
||||
Copyright (C) 1999,2000,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.Entity;
|
||||
|
||||
/**
|
||||
* <p> "Entity" implementation. This is a non-core DOM class, supporting the
|
||||
* "XML" feature. There are two types of entities, neither of which works
|
||||
* particularly well in this API:</p><dl>
|
||||
*
|
||||
* <dt><em>Unparsed Entities</em></dt>
|
||||
* <dd>Since ENTITY/ENTITIES attributes, the only legal use of unparsed
|
||||
* entities in XML, can't be detected with DOM, there isn't much point in
|
||||
* trying to use unparsed entities in DOM applications. (XML Linking is
|
||||
* working to provide a better version of this functionality.) </dd>
|
||||
*
|
||||
* <dt><em>Parsed Entities</em></dt>
|
||||
* <dd> While the DOM specification permits nodes for parsed entities
|
||||
* to have a readonly set of children, this is not required and there
|
||||
* is no portable way to provide such children. <em>This implementation
|
||||
* currently does not permit children to be added to Entities.</em>
|
||||
* There are related issues with the use of EntityReference nodes. </dd>
|
||||
*
|
||||
* </dl>
|
||||
*
|
||||
* <p> In short, <em>avoid using this DOM functionality</em>.
|
||||
*
|
||||
* @see DomDoctype
|
||||
* @see DomEntityReference
|
||||
* @see DomNotation
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomEntity
|
||||
extends DomExtern
|
||||
implements Entity
|
||||
{
|
||||
|
||||
private String notation;
|
||||
|
||||
/**
|
||||
* Constructs an Entity node associated with the specified document,
|
||||
* with the specified descriptive data.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a DomDoctype as part
|
||||
* of its declareEntity functionality, or through a subclass which is
|
||||
* similarly used in a "Sub-DOM" style layer.
|
||||
*
|
||||
* @param owner The document with which this entity is associated
|
||||
* @param name Name of this entity
|
||||
* @param publicId If non-null, provides the entity's PUBLIC identifier
|
||||
* @param systemId Provides the entity's SYSTEM identifier (URI)
|
||||
* @param notation If non-null, provides the unparsed entity's notation.
|
||||
*/
|
||||
protected DomEntity(DomDocument owner,
|
||||
String name,
|
||||
String publicId,
|
||||
String systemId,
|
||||
String notation)
|
||||
{
|
||||
super(ENTITY_NODE, owner, name, publicId, systemId);
|
||||
this.notation = notation;
|
||||
|
||||
// NOTE: if notation == null, this is a parsed entity
|
||||
// which could reasonably be given child nodes ...
|
||||
makeReadonly();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the NOTATION identifier associated with this entity, if any.
|
||||
*/
|
||||
final public String getNotationName()
|
||||
{
|
||||
return notation;
|
||||
}
|
||||
|
||||
// DOM Level 3 methods
|
||||
|
||||
public String getInputEncoding()
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getXmlEncoding()
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getXmlVersion()
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The base URI of an external entity is its system ID.
|
||||
* The base URI of an internal entity is the parent document's base URI.
|
||||
* @since DOM Level 3 Core
|
||||
*/
|
||||
public String getBaseURI()
|
||||
{
|
||||
String systemId = getSystemId();
|
||||
return (systemId == null) ? owner.getBaseURI() : systemId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/* DomEntityReference.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.Entity;
|
||||
import org.w3c.dom.EntityReference;
|
||||
|
||||
/**
|
||||
* <p> "EntityReference" implementation (reference to parsed entity).
|
||||
* This is a non-core DOM class, supporting the "XML" feature.
|
||||
* It does not represent builtin entities (such as "&amp;")
|
||||
* or character references, which are always directly expanded in
|
||||
* DOM trees.</p>
|
||||
*
|
||||
* <p> Note that while the DOM specification permits these nodes to have
|
||||
* a readonly set of children, this is not required. Similarly, it does
|
||||
* not require a DOM to couple EntityReference nodes with any Entity nodes
|
||||
* that have the same entity name (and equivalent children). It also
|
||||
* effectively guarantees that references created directly or indirectly
|
||||
* through the <em>Document.ImportNode</em> method will not have children.
|
||||
* The level of functionality you may get is extremely variable.
|
||||
*
|
||||
* <p> Also significant is that even at their most functional level, the fact
|
||||
* that EntityReference children must be readonly has caused significant
|
||||
* problems when modifying work products held in DOM trees. Other problems
|
||||
* include issues related to undeclared namespace prefixes (and references
|
||||
* to the current default namespace) that may be found in the text of such
|
||||
* parsed entities nodes. These must be contextually bound as part of DOM
|
||||
* tree construction. When such nodes are moved, the namespace associated
|
||||
* with a given prefix (or default) may change to be in conflict with the
|
||||
* namespace bound to the node at creation time.
|
||||
*
|
||||
* <p> In short, <em>avoid using this DOM functionality</em>.
|
||||
*
|
||||
* @see DomDoctype
|
||||
* @see DomEntity
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomEntityReference
|
||||
extends DomNode
|
||||
implements EntityReference
|
||||
{
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Constructs an EntityReference node associated with the specified
|
||||
* document. The creator should populate this with whatever contents
|
||||
* are appropriate, and then mark it as readonly.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a Document as part of
|
||||
* its createEntityReference functionality, or through a subclass which
|
||||
* is similarly used in a "Sub-DOM" style layer.
|
||||
*
|
||||
* @see DomNode#makeReadonly
|
||||
*/
|
||||
protected DomEntityReference(DomDocument owner, String name)
|
||||
{
|
||||
super(ENTITY_REFERENCE_NODE, owner);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the referenced entity.
|
||||
* @since DOM Level 1 Core
|
||||
*/
|
||||
public final String getNodeName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The base URI of an entity reference is the base URI where the entity
|
||||
* declaration occurs.
|
||||
* @since DOM Level 3 Core
|
||||
*/
|
||||
public final String getBaseURI()
|
||||
{
|
||||
DocumentType doctype = owner.getDoctype();
|
||||
if (doctype == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Entity entity = (Entity) doctype.getEntities().getNamedItem(name);
|
||||
if (entity == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return entity.getBaseURI();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
/* DomEvent.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
import org.w3c.dom.events.*;
|
||||
import org.w3c.dom.views.AbstractView; // used by UIEvent
|
||||
|
||||
/**
|
||||
* "Event" implementation. Events are
|
||||
* created (through DocumentEvent interface methods on the document object),
|
||||
* and are sent to any target node in the document.
|
||||
*
|
||||
* <p> Applications may define application specific event subclasses, but
|
||||
* should otherwise use the <em>DocumentTraversal</em> interface to acquire
|
||||
* event objects.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class DomEvent
|
||||
implements Event
|
||||
{
|
||||
|
||||
String type; // init
|
||||
EventTarget target;
|
||||
EventTarget currentNode;
|
||||
short eventPhase;
|
||||
boolean bubbles; // init
|
||||
boolean cancelable; // init
|
||||
long timeStamp; // ?
|
||||
|
||||
/** Returns the event's type (name) as initialized */
|
||||
public final String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns event's target; delivery of an event is initiated
|
||||
* by a <em>target.dispatchEvent(event)</em> invocation.
|
||||
*/
|
||||
public final EventTarget getTarget()
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target to which events are currently being
|
||||
* delivered. When capturing or bubbling, this will not
|
||||
* be what <em>getTarget</em> returns.
|
||||
*/
|
||||
public final EventTarget getCurrentTarget()
|
||||
{
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns CAPTURING_PHASE, AT_TARGET, or BUBBLING;
|
||||
* only meaningful within EventListener.handleEvent
|
||||
*/
|
||||
public final short getEventPhase()
|
||||
{
|
||||
return eventPhase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the news of the event bubbles to tree tops
|
||||
* (as specified during initialization).
|
||||
*/
|
||||
public final boolean getBubbles()
|
||||
{
|
||||
return bubbles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the default handling may be canceled
|
||||
* (as specified during initialization).
|
||||
*/
|
||||
public final boolean getCancelable()
|
||||
{
|
||||
return cancelable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event's timestamp.
|
||||
*/
|
||||
public final long getTimeStamp()
|
||||
{
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
boolean stop;
|
||||
boolean doDefault;
|
||||
|
||||
/**
|
||||
* Requests the event no longer be captured or bubbled; only
|
||||
* listeners on the event target will see the event, if they
|
||||
* haven't yet been notified.
|
||||
*
|
||||
* <p> <em> Avoid using this </em> except for application-specific
|
||||
* events, for which you the protocol explicitly "blesses" the use
|
||||
* of this with some event types. Otherwise, you are likely to break
|
||||
* algorithms which depend on event notification either directly or
|
||||
* through bubbling or capturing. </p>
|
||||
*
|
||||
* <p> Note that this method is not final, specifically to enable
|
||||
* enforcing of policies about events always propagating. </p>
|
||||
*/
|
||||
public void stopPropagation()
|
||||
{
|
||||
stop = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that whoever dispatched the event not perform their
|
||||
* default processing when event delivery completes. Initializes
|
||||
* event timestamp.
|
||||
*/
|
||||
public final void preventDefault()
|
||||
{
|
||||
doDefault = false;
|
||||
}
|
||||
|
||||
/** Initializes basic event state. */
|
||||
public void initEvent(String typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg)
|
||||
{
|
||||
eventPhase = 0;
|
||||
type = typeArg;
|
||||
bubbles = canBubbleArg;
|
||||
cancelable = cancelableArg;
|
||||
timeStamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/** Constructs, but does not initialize, an event. */
|
||||
public DomEvent(String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a basic printable description of the event's type,
|
||||
* state, and delivery conditions
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer("[Event ");
|
||||
buf.append(type);
|
||||
switch (eventPhase)
|
||||
{
|
||||
case CAPTURING_PHASE:
|
||||
buf.append(", CAPTURING");
|
||||
break;
|
||||
case AT_TARGET:
|
||||
buf.append(", AT TARGET");
|
||||
break;
|
||||
case BUBBLING_PHASE:
|
||||
buf.append(", BUBBLING");
|
||||
break;
|
||||
default:
|
||||
buf.append(", (inactive)");
|
||||
break;
|
||||
}
|
||||
if (bubbles && eventPhase != BUBBLING_PHASE)
|
||||
{
|
||||
buf.append(", bubbles");
|
||||
}
|
||||
if (cancelable)
|
||||
{
|
||||
buf.append(", can cancel");
|
||||
}
|
||||
// were we to provide subclass info, this's where it'd live
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* "MutationEvent" implementation.
|
||||
*/
|
||||
public static final class DomMutationEvent
|
||||
extends DomEvent
|
||||
implements MutationEvent
|
||||
{
|
||||
|
||||
// package private
|
||||
Node relatedNode; // init
|
||||
|
||||
private String prevValue; // init
|
||||
private String newValue; // init
|
||||
|
||||
private String attrName; // init
|
||||
private short attrChange; // init
|
||||
|
||||
/** Returns any "related" node provided by this type of event */
|
||||
public final Node getRelatedNode()
|
||||
{
|
||||
return relatedNode;
|
||||
}
|
||||
|
||||
/** Returns any "previous value" provided by this type of event */
|
||||
public final String getPrevValue()
|
||||
{
|
||||
return prevValue;
|
||||
}
|
||||
|
||||
/** Returns any "new value" provided by this type of event */
|
||||
public final String getNewValue()
|
||||
{
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/** For attribute change events, returns the attribute's name */
|
||||
public final String getAttrName()
|
||||
{
|
||||
return attrName;
|
||||
}
|
||||
|
||||
/** For attribute change events, returns how the attribuet changed */
|
||||
public final short getAttrChange()
|
||||
{
|
||||
return attrChange;
|
||||
}
|
||||
|
||||
/** Initializes a mutation event */
|
||||
public final void initMutationEvent(String typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
Node relatedNodeArg,
|
||||
String prevValueArg,
|
||||
String newValueArg,
|
||||
String attrNameArg,
|
||||
short attrChangeArg)
|
||||
{
|
||||
// super.initEvent is inlined here for speed
|
||||
// (mutation events are issued on all DOM changes)
|
||||
eventPhase = 0;
|
||||
type = typeArg;
|
||||
bubbles = canBubbleArg;
|
||||
cancelable = cancelableArg;
|
||||
timeStamp = System.currentTimeMillis();
|
||||
|
||||
relatedNode = relatedNodeArg;
|
||||
prevValue = prevValueArg;
|
||||
newValue = newValueArg;
|
||||
attrName = attrNameArg;
|
||||
attrChange = attrChangeArg;
|
||||
}
|
||||
|
||||
// clear everything that should be GC-able
|
||||
void clear()
|
||||
{
|
||||
type = null;
|
||||
target = null;
|
||||
relatedNode = null;
|
||||
currentNode = null;
|
||||
prevValue = newValue = attrName = null;
|
||||
}
|
||||
|
||||
/** Constructs an uninitialized mutation event. */
|
||||
public DomMutationEvent(String type)
|
||||
{
|
||||
super(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* "UIEvent" implementation.
|
||||
*/
|
||||
public static class DomUIEvent
|
||||
extends DomEvent
|
||||
implements UIEvent
|
||||
{
|
||||
|
||||
private AbstractView view; // init
|
||||
private int detail; // init
|
||||
|
||||
/** Constructs an uninitialized User Interface (UI) event */
|
||||
public DomUIEvent (String type) { super (type); }
|
||||
|
||||
public final AbstractView getView () { return view; }
|
||||
public final int getDetail () { return detail; }
|
||||
|
||||
/** Initializes a UI event */
|
||||
public final void initUIEvent(String typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
AbstractView viewArg,
|
||||
int detailArg)
|
||||
{
|
||||
super.initEvent(typeArg, canBubbleArg, cancelableArg);
|
||||
view = viewArg;
|
||||
detail = detailArg;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
static final class DomMouseEvent extends DomUIEvent
|
||||
implements MouseEvent
|
||||
{
|
||||
// another half dozen state variables/accessors
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/* DomEx.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* <p> DOMException implementation. The version that
|
||||
* is provided by the W3C is abstract, so it can't be instantiated.
|
||||
*
|
||||
* <p> This also provides a bit more information about the error
|
||||
* that is being reported, in terms of the relevant DOM structures
|
||||
* and data.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class DomEx
|
||||
extends DOMException
|
||||
{
|
||||
|
||||
/** @serial Data that caused an error to be reported */
|
||||
private String data;
|
||||
|
||||
/** @serial Node associated with the error. */
|
||||
private Node node;
|
||||
|
||||
/** @serial Data associated with the error. */
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* Constructs an exception, with the diagnostic message
|
||||
* corresponding to the specified code.
|
||||
*/
|
||||
public DomEx(short code)
|
||||
{
|
||||
super(code, diagnostic(code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception, with the diagnostic message
|
||||
* corresponding to the specified code and additional
|
||||
* information as provided.
|
||||
*/
|
||||
public DomEx(short code, String data, Node node, int value)
|
||||
{
|
||||
super(code, diagnostic(code));
|
||||
this.data = data;
|
||||
this.node = node;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/** Returns the node to which the diagnotic applies, or null. */
|
||||
final public Node getNode()
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Returns data to which the diagnotic applies, or null. */
|
||||
final public String getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Returns data to which the diagnotic applies, or null. */
|
||||
final public int getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a diagnostic message that may be slightly more useful
|
||||
* than the generic one, where possible.
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
String retval = super.getMessage();
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
retval += "\nMore Information: " + data;
|
||||
}
|
||||
if (value != 0)
|
||||
{
|
||||
retval += "\nNumber: " + value;
|
||||
}
|
||||
if (node != null)
|
||||
{
|
||||
retval += "\nNode Name: " + node.getNodeName();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// these strings should be localizable.
|
||||
|
||||
private static String diagnostic(short code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
// DOM L1:
|
||||
case INDEX_SIZE_ERR:
|
||||
return "An index or size is out of range.";
|
||||
case DOMSTRING_SIZE_ERR:
|
||||
return "A string is too big.";
|
||||
case HIERARCHY_REQUEST_ERR:
|
||||
return "The node doesn't belong here.";
|
||||
case WRONG_DOCUMENT_ERR:
|
||||
return "The node belongs in another document.";
|
||||
case INVALID_CHARACTER_ERR:
|
||||
return "That character is not permitted.";
|
||||
case NO_DATA_ALLOWED_ERR:
|
||||
return "This node does not permit data.";
|
||||
case NO_MODIFICATION_ALLOWED_ERR:
|
||||
return "No changes are allowed.";
|
||||
case NOT_FOUND_ERR:
|
||||
return "The node was not found in that context.";
|
||||
case NOT_SUPPORTED_ERR:
|
||||
return "That object is not supported.";
|
||||
case INUSE_ATTRIBUTE_ERR:
|
||||
return "The attribute belongs to a different element.";
|
||||
|
||||
// DOM L2:
|
||||
case INVALID_STATE_ERR:
|
||||
return "The object is not usable.";
|
||||
case SYNTAX_ERR:
|
||||
return "An illegal string was provided.";
|
||||
case INVALID_MODIFICATION_ERR:
|
||||
return "An object's type may not be changed.";
|
||||
case NAMESPACE_ERR:
|
||||
return "The operation violates XML Namespaces.";
|
||||
case INVALID_ACCESS_ERR:
|
||||
return "Parameter or operation isn't supported by this node.";
|
||||
case TYPE_MISMATCH_ERR:
|
||||
return "The type of the argument is incompatible with the expected type.";
|
||||
}
|
||||
return "Reserved exception number: " + code;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/* DomExtern.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
/**
|
||||
* <p> Abstract implemention of nodes describing external DTD-related
|
||||
* objects. This facilitates reusing code for Entity, Notation, and
|
||||
* DocumentType (really, external subset) nodes. Such support is not
|
||||
* part of the core DOM; it's for the "XML" feature. </p>
|
||||
*
|
||||
* <p> Note that you are strongly advised to avoid using the DOM
|
||||
* features that take advantage of this class, since (as of L2) none
|
||||
* of them is defined fully enough to permit full use of the
|
||||
* XML feature they partially expose. </p>
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public abstract class DomExtern
|
||||
extends DomNode
|
||||
{
|
||||
|
||||
private final String name;
|
||||
private final String publicId;
|
||||
private final String systemId;
|
||||
|
||||
/**
|
||||
* Constructs a node associated with the specified document,
|
||||
* with the specified descriptive data.
|
||||
*
|
||||
* @param owner The document with which this object is associated
|
||||
* @param name Name of this object
|
||||
* @param publicId If non-null, provides the entity's PUBLIC identifier
|
||||
* @param systemId If non-null, provides the entity's SYSTEM identifier
|
||||
*/
|
||||
// package private
|
||||
DomExtern(short nodeType,
|
||||
DomDocument owner,
|
||||
String name,
|
||||
String publicId,
|
||||
String systemId)
|
||||
{
|
||||
super(nodeType, owner);
|
||||
this.name = name;
|
||||
this.publicId = publicId;
|
||||
this.systemId = systemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the SYSTEM identifier associated with this object, if any.
|
||||
*/
|
||||
public final String getSystemId()
|
||||
{
|
||||
return systemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the PUBLIC identifier associated with this object, if any.
|
||||
*/
|
||||
public final String getPublicId()
|
||||
{
|
||||
return publicId;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the object's name.
|
||||
*/
|
||||
public final String getNodeName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public final String getLocalName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/* DomFragment.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
|
||||
/**
|
||||
* <p> "DocumentFragment" implementation. </p>
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomFragment
|
||||
extends DomNode
|
||||
implements DocumentFragment
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs a DocumentFragment node associated with the
|
||||
* specified document.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a Document as part of
|
||||
* its createDocumentFragment functionality, or through a subclass which
|
||||
* is similarly used in a "Sub-DOM" style layer.
|
||||
*/
|
||||
protected DomFragment(DomDocument owner)
|
||||
{
|
||||
super(DOCUMENT_FRAGMENT_NODE, owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the string "#document-fragment".
|
||||
*/
|
||||
final public String getNodeName()
|
||||
{
|
||||
return "#document-fragment";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/* DomImpl.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.ls.DOMImplementationLS;
|
||||
import org.w3c.dom.ls.LSInput;
|
||||
import org.w3c.dom.ls.LSOutput;
|
||||
import org.w3c.dom.ls.LSParser;
|
||||
import org.w3c.dom.ls.LSSerializer;
|
||||
import gnu.xml.dom.ls.DomLSInput;
|
||||
import gnu.xml.dom.ls.DomLSOutput;
|
||||
import gnu.xml.dom.ls.DomLSParser;
|
||||
import gnu.xml.dom.ls.DomLSSerializer;
|
||||
|
||||
/**
|
||||
* <p> "DOMImplementation" implementation. </p>
|
||||
*
|
||||
* <p> At this writing, the following features are supported:
|
||||
* "XML" (L1, L2, L3),
|
||||
* "Events" (L2), "MutationEvents" (L2), "USER-Events" (a conformant extension),
|
||||
* "HTMLEvents" (L2), "UIEvents" (L2), "Traversal" (L2), "XPath" (L3),
|
||||
* "LS" (L3) "LS-Async" (L3).
|
||||
* It is possible to compile the package so it doesn't support some of these
|
||||
* features (notably, Traversal).
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomImpl
|
||||
implements DOMImplementation, DOMImplementationLS
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs a DOMImplementation object which supports
|
||||
* "XML" and other DOM Level 2 features.
|
||||
*/
|
||||
public DomImpl()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns true if the specified feature and version are
|
||||
* supported. Note that the case of the feature name is ignored.
|
||||
*/
|
||||
public boolean hasFeature(String name, String version)
|
||||
{
|
||||
if (name.length() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
name = name.toLowerCase();
|
||||
if (name.charAt(0) == '+')
|
||||
{
|
||||
name = name.substring(1);
|
||||
}
|
||||
|
||||
if ("xml".equals(name) || "core".equals(name))
|
||||
{
|
||||
return (version == null ||
|
||||
"".equals(version) ||
|
||||
"1.0".equals(version) ||
|
||||
"2.0".equals(version) ||
|
||||
"3.0".equals(version));
|
||||
|
||||
}
|
||||
else if ("ls".equals(name) || "ls-async".equals(name))
|
||||
{
|
||||
return (version == null ||
|
||||
"".equals(version) ||
|
||||
"3.0".equals(version));
|
||||
}
|
||||
else if ("events".equals(name)
|
||||
|| "mutationevents".equals(name)
|
||||
|| "uievents".equals(name)
|
||||
// || "mouseevents".equals(name)
|
||||
|| "htmlevents".equals(name))
|
||||
{
|
||||
return (version == null ||
|
||||
"".equals(version) ||
|
||||
"2.0".equals(version));
|
||||
|
||||
// Extension: "USER-" prefix event types can
|
||||
// be created and passed through the DOM.
|
||||
|
||||
}
|
||||
else if ("user-events".equals(name))
|
||||
{
|
||||
return (version == null ||
|
||||
"".equals(version) ||
|
||||
"0.1".equals(version));
|
||||
|
||||
// NOTE: "hasFeature" for events is here interpreted to
|
||||
// mean the DOM can manufacture those sorts of events,
|
||||
// since actually choosing to report the events is more
|
||||
// often part of the environment or application. It's
|
||||
// only really an issue for mutation events.
|
||||
|
||||
}
|
||||
else if (DomNode.reportMutations
|
||||
&& "traversal".equals(name))
|
||||
{
|
||||
return (version == null ||
|
||||
"".equals(version) ||
|
||||
"2.0".equals(version));
|
||||
}
|
||||
else if ("xpath".equals(name))
|
||||
{
|
||||
return (version == null ||
|
||||
"".equals(version) ||
|
||||
"3.0".equals(version));
|
||||
}
|
||||
|
||||
// views
|
||||
// stylesheets
|
||||
// css, css2
|
||||
// range
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Creates and returns a DocumentType, associated with this
|
||||
* implementation. This DocumentType can have no associated
|
||||
* objects(notations, entities) until the DocumentType is
|
||||
* first associated with a document.
|
||||
*
|
||||
* <p> Note that there is no implication that this DTD will
|
||||
* be parsed by the DOM, or ever have contents. Moreover, the
|
||||
* DocumentType created here can only be added to a document by
|
||||
* the createDocument method(below). <em>That means that the only
|
||||
* portable way to create a Document object is to start parsing,
|
||||
* queue comment and processing instruction (PI) nodes, and then only
|
||||
* create a DOM Document after <b>(a)</b> it's known if a DocumentType
|
||||
* object is needed, and <b>(b) the name and namespace of the root
|
||||
* element is known. Queued comment and PI nodes would then be
|
||||
* inserted appropriately in the document prologue, both before and
|
||||
* after the DTD node, and additional attributes assigned to the
|
||||
* root element.</em>
|
||||
*(One hopes that the final DOM REC fixes this serious botch.)
|
||||
*/
|
||||
public DocumentType createDocumentType(String rootName,
|
||||
String publicId,
|
||||
String systemId)
|
||||
// CR2 deleted internal subset, ensuring DocumentType
|
||||
// is 100% useless instead of just 90% so.
|
||||
{
|
||||
DomDocument.checkNCName(rootName, false);
|
||||
return new DomDoctype(this, rootName, publicId, systemId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Creates and returns a Document, populated only with a root element and
|
||||
* optionally a document type(if that was provided).
|
||||
*/
|
||||
public Document createDocument(String namespaceURI,
|
||||
String rootName,
|
||||
DocumentType doctype)
|
||||
{
|
||||
Document doc = new DomDocument(this);
|
||||
Element root = null;
|
||||
|
||||
if (rootName != null)
|
||||
{
|
||||
root = doc.createElementNS(namespaceURI, rootName);
|
||||
if (rootName.startsWith("xmlns:"))
|
||||
{
|
||||
throw new DomEx(DomEx.NAMESPACE_ERR, "xmlns is reserved", null, 0);
|
||||
}
|
||||
}
|
||||
// Bleech -- L2 seemingly _requires_ omission of xmlns attributes.
|
||||
if (doctype != null)
|
||||
{
|
||||
doc.appendChild(doctype); // handles WRONG_DOCUMENT error
|
||||
}
|
||||
if (root != null)
|
||||
{
|
||||
doc.appendChild(root);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
// DOM Level 3
|
||||
|
||||
public Object getFeature(String feature, String version)
|
||||
{
|
||||
if (hasFeature(feature, version))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// -- DOMImplementationLS --
|
||||
|
||||
public LSParser createLSParser(short mode, String schemaType)
|
||||
throws DOMException
|
||||
{
|
||||
return new DomLSParser(mode, schemaType);
|
||||
}
|
||||
|
||||
public LSSerializer createLSSerializer()
|
||||
{
|
||||
return new DomLSSerializer();
|
||||
}
|
||||
|
||||
public LSInput createLSInput()
|
||||
{
|
||||
return new DomLSInput();
|
||||
}
|
||||
|
||||
public LSOutput createLSOutput()
|
||||
{
|
||||
return new DomLSOutput();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
/* DomIterator.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.events.Event;
|
||||
import org.w3c.dom.events.EventListener;
|
||||
import org.w3c.dom.events.EventTarget;
|
||||
import org.w3c.dom.events.MutationEvent;
|
||||
import org.w3c.dom.traversal.NodeFilter;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
|
||||
/**
|
||||
* <p> "NodeIterator" implementation, usable with any L2 DOM which
|
||||
* supports MutationEvents. </p>
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public final class DomIterator
|
||||
implements NodeIterator, EventListener
|
||||
{
|
||||
|
||||
private Node reference;
|
||||
private boolean right;
|
||||
private boolean done;
|
||||
|
||||
private final Node root;
|
||||
private final int whatToShow;
|
||||
private final NodeFilter filter;
|
||||
private final boolean expandEntityReferences;
|
||||
|
||||
/**
|
||||
* Constructs and initializes an iterator.
|
||||
*/
|
||||
protected DomIterator(Node root,
|
||||
int whatToShow,
|
||||
NodeFilter filter,
|
||||
boolean entityReferenceExpansion)
|
||||
{
|
||||
if (!root.isSupported("MutationEvents", "2.0"))
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_SUPPORTED_ERR,
|
||||
"Iterator needs mutation events", root, 0);
|
||||
}
|
||||
|
||||
this.root = root;
|
||||
this.whatToShow = whatToShow;
|
||||
this.filter = filter;
|
||||
this.expandEntityReferences = entityReferenceExpansion;
|
||||
|
||||
// start condition: going right, seen nothing yet.
|
||||
reference = null;
|
||||
right = true;
|
||||
|
||||
EventTarget target = (EventTarget) root;
|
||||
target.addEventListener("DOMNodeRemoved", this, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Flags the iterator as done, unregistering its event listener so
|
||||
* that the iterator can be garbage collected without relying on weak
|
||||
* references (a "Java 2" feature) in the event subsystem.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
EventTarget target = (EventTarget) root;
|
||||
target.removeEventListener("DOMNodeRemoved", this, false);
|
||||
done = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the flag controlling whether iteration descends
|
||||
* through entity references.
|
||||
*/
|
||||
public boolean getExpandEntityReferences()
|
||||
{
|
||||
return expandEntityReferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the filter provided during construction.
|
||||
*/
|
||||
public NodeFilter getFilter()
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the root of the tree this is iterating through.
|
||||
*/
|
||||
public Node getRoot()
|
||||
{
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the mask of flags provided during construction.
|
||||
*/
|
||||
public int getWhatToShow()
|
||||
{
|
||||
return whatToShow;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the next node in a forward iteration, masked and filtered.
|
||||
* Note that the node may be read-only due to entity expansions.
|
||||
* A null return indicates the iteration is complete, but may still
|
||||
* be processed backwards.
|
||||
*/
|
||||
public Node nextNode()
|
||||
{
|
||||
if (done)
|
||||
{
|
||||
throw new DomEx(DomEx.INVALID_STATE_ERR);
|
||||
}
|
||||
right = true;
|
||||
return walk(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the next node in a backward iteration, masked and filtered.
|
||||
* Note that the node may be read-only due to entity expansions.
|
||||
* A null return indicates the iteration is complete, but may still
|
||||
* be processed forwards.
|
||||
*/
|
||||
public Node previousNode()
|
||||
{
|
||||
if (done)
|
||||
{
|
||||
throw new DomEx(DomEx.INVALID_STATE_ERR);
|
||||
}
|
||||
Node previous = reference;
|
||||
right = false;
|
||||
walk(false);
|
||||
return previous;
|
||||
}
|
||||
|
||||
private boolean shouldShow(Node node)
|
||||
// raises Runtime exceptions indirectly, via acceptNode()
|
||||
{
|
||||
if ((whatToShow & (1 << (node.getNodeType() - 1))) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (filter == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return filter.acceptNode(node) == NodeFilter.FILTER_ACCEPT;
|
||||
}
|
||||
|
||||
//
|
||||
// scenario: root = 1, sequence = 1 2 ... 3 4
|
||||
// forward walk: 1 2 ... 3 4 null
|
||||
// then backward: 4 3 ... 2 1 null
|
||||
//
|
||||
// At the leftmost end, "previous" == null
|
||||
// At the rightmost end, "previous" == 4
|
||||
//
|
||||
// The current draft spec really seem to make no sense re the
|
||||
// role of the reference node, so what it says is ignored here.
|
||||
//
|
||||
private Node walk(boolean forward)
|
||||
{
|
||||
Node here = reference;
|
||||
|
||||
while ((here = successor(here, forward)) != null
|
||||
&& !shouldShow(here))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (here != null || !forward)
|
||||
{
|
||||
reference = here;
|
||||
}
|
||||
return here;
|
||||
}
|
||||
|
||||
private boolean isLeaf(Node here)
|
||||
{
|
||||
boolean leaf = !here.hasChildNodes();
|
||||
if (!leaf && !expandEntityReferences)
|
||||
{
|
||||
leaf = (here.getNodeType() == Node.ENTITY_REFERENCE_NODE);
|
||||
}
|
||||
return leaf;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the immediate successor in a forward (or backward)
|
||||
// document order walk, sans filtering ... except that it knows
|
||||
// how to stop, returning null when done. This is a depth first
|
||||
// preorder traversal when run in the forward direction.
|
||||
//
|
||||
private Node successor(Node here, boolean forward)
|
||||
{
|
||||
Node next;
|
||||
|
||||
// the "leftmost" end is funky
|
||||
if (here == null)
|
||||
{
|
||||
return forward ? root : null;
|
||||
}
|
||||
|
||||
//
|
||||
// Forward, this is preorder: children before siblings.
|
||||
// Backward, it's postorder: we saw the children already.
|
||||
//
|
||||
if (forward && !isLeaf(here))
|
||||
{
|
||||
return here.getFirstChild();
|
||||
}
|
||||
|
||||
//
|
||||
// Siblings ... if forward, we visit them, if backwards
|
||||
// we visit their children first.
|
||||
//
|
||||
if (forward)
|
||||
{
|
||||
if ((next = here.getNextSibling()) != null)
|
||||
{
|
||||
return next;
|
||||
}
|
||||
}
|
||||
else if ((next = here.getPreviousSibling()) != null)
|
||||
{
|
||||
if (isLeaf(next))
|
||||
{
|
||||
return next;
|
||||
}
|
||||
next = next.getLastChild();
|
||||
while (!isLeaf(next))
|
||||
{
|
||||
next = next.getLastChild();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
//
|
||||
// We can't go down or lateral -- it's up, then. The logic is
|
||||
// the converse of what's above: backwards is easy (the parent
|
||||
// is next), forwards isn't.
|
||||
//
|
||||
next = here.getParentNode();
|
||||
if (!forward)
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
Node temp = null;
|
||||
while (next != null
|
||||
&& next != root
|
||||
&& (temp = next.getNextSibling()) == null)
|
||||
{
|
||||
next = next.getParentNode();
|
||||
}
|
||||
if (next == root)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not for public use. This lets the iterator know when its
|
||||
* reference node will be removed from the tree, so that a new
|
||||
* one may be selected.
|
||||
*
|
||||
* <p> This version works by watching removal events as they
|
||||
* bubble up. So, don't prevent them from bubbling.
|
||||
*/
|
||||
public void handleEvent(Event e)
|
||||
{
|
||||
MutationEvent event;
|
||||
Node ancestor, removed;
|
||||
|
||||
if (reference == null
|
||||
|| !"DOMNodeRemoved".equals(e.getType())
|
||||
|| e.getEventPhase() != Event.BUBBLING_PHASE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
event = (MutationEvent) e;
|
||||
removed = (Node) event.getTarget();
|
||||
|
||||
// See if the removal will cause trouble for this iterator
|
||||
// by being the reference node or an ancestor of it.
|
||||
for (ancestor = reference;
|
||||
ancestor != null && ancestor != root;
|
||||
ancestor = ancestor.getParentNode())
|
||||
{
|
||||
if (ancestor == removed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ancestor != removed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// OK, it'll cause trouble. We want to make the "next"
|
||||
// node in our current traversal direction seem right.
|
||||
// So we pick the nearest node that's not getting removed,
|
||||
// but go in the _opposite_ direction from our current
|
||||
// traversal ... so the "next" doesn't skip anything.
|
||||
Node candidate;
|
||||
|
||||
search:
|
||||
while ((candidate = walk(!right)) != null)
|
||||
{
|
||||
for (ancestor = candidate;
|
||||
ancestor != null && ancestor != root;
|
||||
ancestor = ancestor.getParentNode())
|
||||
{
|
||||
if (ancestor == removed)
|
||||
{
|
||||
continue search;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// The current DOM WD talks about a special case here;
|
||||
// I've not yet seen it.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/* DomNSResolverContext.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.Iterator;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import org.w3c.dom.xpath.XPathNSResolver;
|
||||
|
||||
/**
|
||||
* Namespace content wrapper for an XPathNSResolver.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DomNSResolverContext
|
||||
implements NamespaceContext, Iterator
|
||||
{
|
||||
|
||||
final XPathNSResolver resolver;
|
||||
|
||||
DomNSResolverContext(XPathNSResolver resolver)
|
||||
{
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
public String getNamespaceURI(String prefix)
|
||||
{
|
||||
return resolver.lookupNamespaceURI(prefix);
|
||||
}
|
||||
|
||||
public String getPrefix(String namespaceURI)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Iterator getPrefixes(String namespaceURI)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasNext()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object next()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void remove()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
/* DomNamedNodeMap.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* <p> "NamedNodeMap" implementation. </p>
|
||||
* Used mostly to hold element attributes, but sometimes also
|
||||
* to list notations or entities.
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomNamedNodeMap
|
||||
implements NamedNodeMap
|
||||
{
|
||||
|
||||
final DomNode owner;
|
||||
final short type;
|
||||
|
||||
DomNode first;
|
||||
int length;
|
||||
boolean readonly;
|
||||
|
||||
// package private
|
||||
DomNamedNodeMap(DomNode owner, short type)
|
||||
{
|
||||
this.owner = owner;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the internal "readonly" flag. In DOM, all NamedNodeMap
|
||||
* objects found in a DocumentType object are read-only (after
|
||||
* they are fully constructed), and those holding attributes of
|
||||
* a readonly element will also be readonly.
|
||||
*/
|
||||
public final boolean isReadonly()
|
||||
{
|
||||
return readonly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal "readonly" flag so the node and its
|
||||
* children can't be changed.
|
||||
*/
|
||||
public void makeReadonly()
|
||||
{
|
||||
readonly = true;
|
||||
for (DomNode ctx = first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
ctx.makeReadonly();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the named item from the map, or null; names are just
|
||||
* the nodeName property.
|
||||
*/
|
||||
public Node getNamedItem(String name)
|
||||
{
|
||||
for (DomNode ctx = first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
if (ctx.getNodeName().equals(name))
|
||||
{
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the named item from the map, or null; names are the
|
||||
* localName and namespaceURI properties, ignoring any prefix.
|
||||
*/
|
||||
public Node getNamedItemNS(String namespaceURI, String localName)
|
||||
{
|
||||
if ("".equals(namespaceURI))
|
||||
{
|
||||
namespaceURI = null;
|
||||
}
|
||||
for (DomNode ctx = first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
String name = ctx.getLocalName();
|
||||
if ((localName == null && name == null) ||
|
||||
(localName != null && localName.equals(name)))
|
||||
{
|
||||
String uri = ctx.getNamespaceURI();
|
||||
if ("".equals(uri))
|
||||
{
|
||||
uri = null;
|
||||
}
|
||||
if ((namespaceURI == null && uri == null) ||
|
||||
(namespaceURI != null && namespaceURI.equals(uri)))
|
||||
{
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Stores the named item into the map, optionally overwriting
|
||||
* any existing node with that name. The name used is just
|
||||
* the nodeName attribute.
|
||||
*/
|
||||
public Node setNamedItem(Node arg)
|
||||
{
|
||||
return setNamedItem(arg, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Stores the named item into the map, optionally overwriting
|
||||
* any existing node with that fully qualified name. The name
|
||||
* used incorporates the localName and namespaceURI properties,
|
||||
* and ignores any prefix.
|
||||
*/
|
||||
public Node setNamedItemNS(Node arg)
|
||||
{
|
||||
return setNamedItem(arg, true);
|
||||
}
|
||||
|
||||
Node setNamedItem(Node arg, boolean ns)
|
||||
{
|
||||
if (readonly)
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
|
||||
DomNode node = (DomNode) arg;
|
||||
if (node.owner != owner.owner)
|
||||
{
|
||||
throw new DomEx(DomEx.WRONG_DOCUMENT_ERR);
|
||||
}
|
||||
if (node.nodeType != type)
|
||||
{
|
||||
throw new DomEx(DomEx.HIERARCHY_REQUEST_ERR);
|
||||
}
|
||||
if (node.nodeType == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
DomNode element = node.parent;
|
||||
if (element != null && element != owner)
|
||||
{
|
||||
throw new DomEx(DomEx.INUSE_ATTRIBUTE_ERR);
|
||||
}
|
||||
node.parent = owner;
|
||||
node.depth = owner.depth + 1;
|
||||
}
|
||||
|
||||
String nodeName = node.getNodeName();
|
||||
String localName = ns ? node.getLocalName() : null;
|
||||
String namespaceURI = ns ? node.getNamespaceURI() : null;
|
||||
if ("".equals(namespaceURI))
|
||||
{
|
||||
namespaceURI = null;
|
||||
}
|
||||
|
||||
// maybe attribute ADDITION events (?)
|
||||
DomNode last = null;
|
||||
for (DomNode ctx = first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
boolean test = false;
|
||||
if (ns)
|
||||
{
|
||||
String tln = ctx.getLocalName();
|
||||
if (tln.equals(localName))
|
||||
{
|
||||
String tu = ctx.getNamespaceURI();
|
||||
if ((tu == null && namespaceURI == null) ||
|
||||
(tu != null && tu.equals(namespaceURI)))
|
||||
{
|
||||
test = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
test = ctx.getNodeName().equals(nodeName);
|
||||
}
|
||||
if (test)
|
||||
{
|
||||
// replace
|
||||
node.previous = ctx.previous;
|
||||
node.next = ctx.next;
|
||||
if (ctx.previous != null)
|
||||
{
|
||||
ctx.previous.next = node;
|
||||
}
|
||||
if (ctx.next != null)
|
||||
{
|
||||
ctx.next.previous = node;
|
||||
}
|
||||
if (first == ctx)
|
||||
{
|
||||
first = node;
|
||||
}
|
||||
reparent(node, nodeName, ctx.index);
|
||||
ctx.parent = null;
|
||||
ctx.next = null;
|
||||
ctx.previous = null;
|
||||
ctx.setDepth(0);
|
||||
ctx.index = 0;
|
||||
return ctx;
|
||||
}
|
||||
last = ctx;
|
||||
}
|
||||
// append
|
||||
if (last != null)
|
||||
{
|
||||
last.next = node;
|
||||
node.previous = last;
|
||||
}
|
||||
else
|
||||
{
|
||||
first = node;
|
||||
}
|
||||
length++;
|
||||
reparent(node, nodeName, 0);
|
||||
return null;
|
||||
}
|
||||
|
||||
void reparent(DomNode node, String nodeName, int i)
|
||||
{
|
||||
node.parent = owner;
|
||||
node.setDepth(owner.depth + 1);
|
||||
// index renumbering
|
||||
for (DomNode ctx = node; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
ctx.index = i++;
|
||||
}
|
||||
// cache xml:space
|
||||
boolean xmlSpace = "xml:space".equals(nodeName);
|
||||
if (xmlSpace && owner instanceof DomElement)
|
||||
{
|
||||
((DomElement) owner).xmlSpace = node.getNodeValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Removes the named item from the map, or reports an exception;
|
||||
* names are just the nodeName property.
|
||||
*/
|
||||
public Node removeNamedItem(String name)
|
||||
{
|
||||
return removeNamedItem(null, name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Removes the named item from the map, or reports an exception;
|
||||
* names are the localName and namespaceURI properties.
|
||||
*/
|
||||
public Node removeNamedItemNS(String namespaceURI, String localName)
|
||||
{
|
||||
return removeNamedItem(namespaceURI, localName, true);
|
||||
}
|
||||
|
||||
Node removeNamedItem(String uri, String name, boolean ns)
|
||||
{
|
||||
if (readonly)
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
|
||||
// report attribute REMOVAL event?
|
||||
|
||||
for (DomNode ctx = first; ctx != null; ctx = ctx.next)
|
||||
{
|
||||
boolean test = false;
|
||||
String nodeName = ctx.getNodeName();
|
||||
if (ns)
|
||||
{
|
||||
String tln = ctx.getLocalName();
|
||||
if (tln.equals(name))
|
||||
{
|
||||
String tu = ctx.getNamespaceURI();
|
||||
if ((tu == null && uri == null) ||
|
||||
(tu != null && tu.equals(uri)))
|
||||
{
|
||||
test = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
test = nodeName.equals(name);
|
||||
}
|
||||
if (test)
|
||||
{
|
||||
// uncache xml:space
|
||||
boolean xmlSpace = "xml:space".equals(nodeName);
|
||||
if (xmlSpace && owner instanceof DomElement)
|
||||
{
|
||||
((DomElement) owner).xmlSpace = "";
|
||||
}
|
||||
// is this a default attribute?
|
||||
if (ctx.nodeType == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
String def = getDefaultValue(ctx.getNodeName());
|
||||
if (def != null)
|
||||
{
|
||||
ctx.setNodeValue(def);
|
||||
((DomAttr) ctx).setSpecified(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// remove
|
||||
if (ctx == first)
|
||||
{
|
||||
first = ctx.next;
|
||||
}
|
||||
if (ctx.previous != null)
|
||||
{
|
||||
ctx.previous.next = ctx.next;
|
||||
}
|
||||
if (ctx.next != null)
|
||||
{
|
||||
ctx.next.previous = ctx.previous;
|
||||
}
|
||||
length--;
|
||||
ctx.previous = null;
|
||||
ctx.next = null;
|
||||
ctx.parent = null;
|
||||
ctx.setDepth(0);
|
||||
ctx.index = 0;
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
throw new DomEx(DomEx.NOT_FOUND_ERR);
|
||||
}
|
||||
|
||||
String getDefaultValue(String name)
|
||||
{
|
||||
DomDoctype doctype = (DomDoctype) owner.owner.getDoctype();
|
||||
if (doctype == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
DTDAttributeTypeInfo info =
|
||||
doctype.getAttributeTypeInfo(owner.getNodeName(), name);
|
||||
if (info == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return info.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the indexed item from the map, or null.
|
||||
*/
|
||||
public Node item(int index)
|
||||
{
|
||||
DomNode ctx = first;
|
||||
int count = 0;
|
||||
while (ctx != null && count < index)
|
||||
{
|
||||
ctx = ctx.next;
|
||||
count++;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the length of the map.
|
||||
*/
|
||||
public int getLength()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,327 @@
|
||||
/* DomNodeIterator.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.traversal.NodeFilter;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
import org.w3c.dom.traversal.TreeWalker;
|
||||
|
||||
/**
|
||||
* Node iterator and tree walker.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomNodeIterator
|
||||
implements NodeIterator, TreeWalker
|
||||
{
|
||||
|
||||
Node root;
|
||||
final int whatToShow;
|
||||
final NodeFilter filter;
|
||||
final boolean entityReferenceExpansion;
|
||||
final boolean walk;
|
||||
Node current;
|
||||
|
||||
public DomNodeIterator(Node root, int whatToShow, NodeFilter filter,
|
||||
boolean entityReferenceExpansion, boolean walk)
|
||||
{
|
||||
if (root == null)
|
||||
{
|
||||
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "null root");
|
||||
}
|
||||
this.root = root;
|
||||
this.whatToShow = whatToShow;
|
||||
this.filter = filter;
|
||||
this.entityReferenceExpansion = entityReferenceExpansion;
|
||||
this.walk = walk;
|
||||
current = root;
|
||||
}
|
||||
|
||||
public Node getRoot()
|
||||
{
|
||||
return root;
|
||||
}
|
||||
|
||||
public int getWhatToShow()
|
||||
{
|
||||
return whatToShow;
|
||||
}
|
||||
|
||||
public NodeFilter getFilter()
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
|
||||
public boolean getExpandEntityReferences()
|
||||
{
|
||||
return entityReferenceExpansion;
|
||||
}
|
||||
|
||||
public Node nextNode()
|
||||
throws DOMException
|
||||
{
|
||||
if (root == null)
|
||||
{
|
||||
throw new DOMException(DOMException.INVALID_STATE_ERR, "null root");
|
||||
}
|
||||
Node ret;
|
||||
do
|
||||
{
|
||||
if (current.equals(root))
|
||||
{
|
||||
ret = root.getFirstChild();
|
||||
}
|
||||
else if (walk)
|
||||
{
|
||||
ret = current.getFirstChild();
|
||||
if (ret == null)
|
||||
{
|
||||
ret = current.getNextSibling();
|
||||
}
|
||||
if (ret == null)
|
||||
{
|
||||
Node tmp = current;
|
||||
ret = tmp.getParentNode();
|
||||
while (!ret.equals(root) && tmp.equals(ret.getLastChild()))
|
||||
{
|
||||
tmp = ret;
|
||||
ret = tmp.getParentNode();
|
||||
}
|
||||
if (ret.equals(root))
|
||||
{
|
||||
ret = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ret.getNextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = current.getNextSibling();
|
||||
}
|
||||
}
|
||||
while (!accept(ret));
|
||||
current = (ret == null) ? current : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Node previousNode()
|
||||
throws DOMException
|
||||
{
|
||||
if (root == null)
|
||||
{
|
||||
throw new DOMException(DOMException.INVALID_STATE_ERR, "null root");
|
||||
}
|
||||
Node ret;
|
||||
do
|
||||
{
|
||||
if (current.equals(root))
|
||||
{
|
||||
ret = current.getLastChild();
|
||||
}
|
||||
else if (walk)
|
||||
{
|
||||
ret = current.getLastChild();
|
||||
if (ret == null)
|
||||
{
|
||||
ret = current.getPreviousSibling();
|
||||
}
|
||||
if (ret == null)
|
||||
{
|
||||
Node tmp = current;
|
||||
ret = tmp.getParentNode();
|
||||
while (!ret.equals(root) && tmp.equals(ret.getFirstChild()))
|
||||
{
|
||||
tmp = ret;
|
||||
ret = tmp.getParentNode();
|
||||
}
|
||||
if (ret.equals(root))
|
||||
{
|
||||
ret = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ret.getPreviousSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = current.getPreviousSibling();
|
||||
}
|
||||
}
|
||||
while (!accept(ret));
|
||||
current = (ret == null) ? current : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Node getCurrentNode()
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
public void setCurrentNode(Node current)
|
||||
throws DOMException
|
||||
{
|
||||
if (current == null)
|
||||
{
|
||||
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "null root");
|
||||
}
|
||||
this.current = current;
|
||||
}
|
||||
|
||||
public Node parentNode()
|
||||
{
|
||||
Node ret = current.getParentNode();
|
||||
if (!accept (ret))
|
||||
{
|
||||
ret = null;
|
||||
}
|
||||
current = (ret == null) ? current : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Node firstChild ()
|
||||
{
|
||||
Node ret = current.getFirstChild();
|
||||
while (!accept(ret))
|
||||
{
|
||||
ret = ret.getNextSibling();
|
||||
}
|
||||
current = (ret == null) ? current : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Node lastChild()
|
||||
{
|
||||
Node ret = current.getLastChild();
|
||||
while (!accept(ret))
|
||||
{
|
||||
ret = ret.getPreviousSibling();
|
||||
}
|
||||
current = (ret == null) ? current : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Node previousSibling()
|
||||
{
|
||||
Node ret = current.getPreviousSibling();
|
||||
while (!accept(ret))
|
||||
{
|
||||
ret = ret.getPreviousSibling();
|
||||
}
|
||||
current = (ret == null) ? current : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Node nextSibling()
|
||||
{
|
||||
Node ret = current.getNextSibling();
|
||||
while (!accept(ret))
|
||||
{
|
||||
ret = ret.getNextSibling();
|
||||
}
|
||||
current = (ret == null) ? current : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void detach()
|
||||
{
|
||||
root = null;
|
||||
}
|
||||
|
||||
boolean accept(Node node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
boolean ret;
|
||||
switch (node.getNodeType())
|
||||
{
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_ATTRIBUTE) != 0;
|
||||
break;
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_CDATA_SECTION) != 0;
|
||||
break;
|
||||
case Node.COMMENT_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_COMMENT) != 0;
|
||||
break;
|
||||
case Node.DOCUMENT_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_DOCUMENT) != 0;
|
||||
break;
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_DOCUMENT_FRAGMENT) != 0;
|
||||
break;
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_DOCUMENT_TYPE) != 0;
|
||||
break;
|
||||
case Node.ELEMENT_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_ELEMENT) != 0;
|
||||
break;
|
||||
case Node.ENTITY_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_ENTITY) != 0;
|
||||
break;
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_ENTITY_REFERENCE) != 0;
|
||||
ret = ret && entityReferenceExpansion;
|
||||
break;
|
||||
case Node.NOTATION_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_NOTATION) != 0;
|
||||
break;
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_PROCESSING_INSTRUCTION) != 0;
|
||||
break;
|
||||
case Node.TEXT_NODE:
|
||||
ret = (whatToShow & NodeFilter.SHOW_TEXT) != 0;
|
||||
break;
|
||||
default:
|
||||
ret = true;
|
||||
}
|
||||
if (ret && filter != null)
|
||||
{
|
||||
ret = (filter.acceptNode(node) == NodeFilter.FILTER_ACCEPT);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/* DomNotation.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.Notation;
|
||||
|
||||
/**
|
||||
* <p> "Notation" implementation. This is a non-core DOM class, supporting
|
||||
* the "XML" feature. </p>
|
||||
*
|
||||
* <p> Although unparsed entities using this notation can be detected using
|
||||
* DOM, neither NOTATIONS nor ENTITY/ENTITIES attributes can be so detected.
|
||||
* More, there is no portable way to construct a Notation node, so there's
|
||||
* no way that vendor-neutral DOM construction APIs could even report a
|
||||
* NOTATION used to identify the intended meaning of a ProcessingInstruction.
|
||||
* </p>
|
||||
*
|
||||
* <p> In short, <em>avoid using this DOM functionality</em>.
|
||||
*
|
||||
* @see DomDoctype
|
||||
* @see DomEntity
|
||||
* @see DomPI
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomNotation
|
||||
extends DomExtern
|
||||
implements Notation
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs a Notation node associated with the specified document,
|
||||
* with the specified descriptive data. Note that at least one of
|
||||
* the PUBLIC and SYSTEM identifiers must be provided; unlike other
|
||||
* external objects in XML, notations may have only a PUBLIC identifier.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a DomDoctype object
|
||||
* as part of its declareNotation functionality, or through a subclass
|
||||
* which is similarly used in a "Sub-DOM" style layer.
|
||||
*
|
||||
* @param owner The document with which this notation is associated
|
||||
* @param name Name of this notation
|
||||
* @param publicId If non-null, provides the notation's PUBLIC identifier
|
||||
* @param systemId If non-null, rovides the notation's SYSTEM identifier
|
||||
*/
|
||||
protected DomNotation(DomDocument owner,
|
||||
String name,
|
||||
String publicId,
|
||||
String systemId)
|
||||
{
|
||||
super(NOTATION_NODE, owner, name, publicId, systemId);
|
||||
makeReadonly();
|
||||
}
|
||||
|
||||
/**
|
||||
* The base URI of an external entity is its system ID.
|
||||
* The base URI of an internal entity is the parent document's base URI.
|
||||
* @since DOM Level 3 Core
|
||||
*/
|
||||
public String getBaseURI()
|
||||
{
|
||||
String systemId = getSystemId();
|
||||
return (systemId == null) ? owner.getBaseURI() : systemId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
/* DomNsNode.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
|
||||
/**
|
||||
* <p> Abstract implemention of namespace support. This facilitates
|
||||
* sharing code for attribute and element nodes.
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public abstract class DomNsNode
|
||||
extends DomNode
|
||||
{
|
||||
|
||||
private String name;
|
||||
private String namespace;
|
||||
private String prefix;
|
||||
private String localName;
|
||||
|
||||
/**
|
||||
* Constructs a node associated with the specified document, and
|
||||
* with the specified namespace information.
|
||||
*
|
||||
* @param owner The document with which this entity is associated
|
||||
* @param namespaceURI Combined with the local part of the name,
|
||||
* this identifies a type of element or attribute; may be null.
|
||||
* If this is the empty string, it is reassigned as null so that
|
||||
* applications only need to test that case.
|
||||
* @param name Name of this node, which may include a prefix
|
||||
*/
|
||||
// package private
|
||||
DomNsNode(short nodeType, DomDocument owner, String namespaceURI, String name)
|
||||
{
|
||||
super(nodeType, owner);
|
||||
setNodeName(name);
|
||||
setNamespaceURI(namespaceURI);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the node's name, including any namespace prefix.
|
||||
*/
|
||||
public final String getNodeName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
final void setNodeName(String name)
|
||||
{
|
||||
this.name = name.intern();
|
||||
int index = name.indexOf(':');
|
||||
if (index == -1)
|
||||
{
|
||||
prefix = null;
|
||||
localName = this.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = name.substring(0, index).intern();
|
||||
localName = name.substring(index + 1).intern();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the node's namespace URI
|
||||
* <em>or null</em> if the node name is not namespace scoped.
|
||||
*/
|
||||
public final String getNamespaceURI()
|
||||
{
|
||||
return namespace;
|
||||
}
|
||||
|
||||
final void setNamespaceURI(String namespaceURI)
|
||||
{
|
||||
if ("".equals(namespaceURI))
|
||||
{
|
||||
namespaceURI = null;
|
||||
}
|
||||
namespace = (namespaceURI == null) ? null : namespaceURI.intern();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns any prefix part of the node's name (before any colon).
|
||||
*/
|
||||
public final String getPrefix()
|
||||
{
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Assigns the prefix part of the node's name (before any colon).
|
||||
*/
|
||||
public final void setPrefix(String prefix)
|
||||
{
|
||||
if (readonly)
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
|
||||
if (prefix == null)
|
||||
{
|
||||
name = localName;
|
||||
return;
|
||||
}
|
||||
else if (namespace == null)
|
||||
{
|
||||
throw new DomEx(DomEx.NAMESPACE_ERR,
|
||||
"can't set prefix, node has no namespace URI",
|
||||
this, 0);
|
||||
}
|
||||
|
||||
DomDocument.checkName(prefix, "1.1".equals(owner.getXmlVersion()));
|
||||
if (prefix.indexOf (':') != -1)
|
||||
{
|
||||
throw new DomEx(DomEx.NAMESPACE_ERR,
|
||||
"illegal prefix " + prefix, this, 0);
|
||||
}
|
||||
|
||||
if (XMLConstants.XML_NS_PREFIX.equals(prefix)
|
||||
&& !XMLConstants.XML_NS_URI.equals(namespace))
|
||||
{
|
||||
throw new DomEx(DomEx.NAMESPACE_ERR,
|
||||
"xml namespace is always " +
|
||||
XMLConstants.XML_NS_URI, this, 0);
|
||||
}
|
||||
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix))
|
||||
{
|
||||
if (namespace != null || getNodeType() != ATTRIBUTE_NODE)
|
||||
{
|
||||
throw new DomEx(DomEx.NAMESPACE_ERR,
|
||||
"xmlns attribute prefix is reserved", this, 0);
|
||||
}
|
||||
}
|
||||
else if (getNodeType () == ATTRIBUTE_NODE
|
||||
&& (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
|
||||
name.startsWith("xmlns:")))
|
||||
{
|
||||
throw new DomEx(DomEx.NAMESPACE_ERR,
|
||||
"namespace declarations can't change names", this, 0);
|
||||
}
|
||||
|
||||
this.prefix = prefix.intern();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L2</b>
|
||||
* Returns the local part of the node's name (after any colon).
|
||||
*/
|
||||
public final String getLocalName()
|
||||
{
|
||||
return localName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/* DomPI.java --
|
||||
Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.ProcessingInstruction;
|
||||
|
||||
/**
|
||||
* <p> "ProcessingInstruction" (PI) implementation.
|
||||
* This is a non-core DOM class, supporting the "XML" feature. </p>
|
||||
*
|
||||
* <p> Unlike other DOM APIs in the "XML" feature, this one fully
|
||||
* exposes the functionality it describes. So there is no reason
|
||||
* inherent in DOM to avoid using this API, unless you want to rely
|
||||
* on NOTATION declarations to associate meaning with your PIs;
|
||||
* there is no vendor-neutal way to record those notations in DOM.</p>
|
||||
*
|
||||
* <p> Also of note is that PI support is part of SAX, so that XML
|
||||
* systems using PIs can choose among multiple APIs. </p>
|
||||
*
|
||||
* @see DomNotation
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomPI
|
||||
extends DomNode
|
||||
implements ProcessingInstruction
|
||||
{
|
||||
|
||||
private String target;
|
||||
private String data;
|
||||
|
||||
/**
|
||||
* Constructs a ProcessingInstruction node associated with the
|
||||
* specified document, with the specified data.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a Document object as
|
||||
* part of its createProcessingInstruction functionality, or through
|
||||
* a subclass which is similarly used in a "Sub-DOM" style layer.
|
||||
*/
|
||||
protected DomPI(DomDocument owner, String target, String data)
|
||||
{
|
||||
super(PROCESSING_INSTRUCTION_NODE, owner);
|
||||
this.target = target;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the target of the processing instruction.
|
||||
*/
|
||||
public final String getTarget()
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the target of the processing instruction
|
||||
* (same as getTarget).
|
||||
*/
|
||||
public final String getNodeName()
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the data associated with the processing instruction.
|
||||
*/
|
||||
public final String getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the data associated with the processing instruction
|
||||
* (same as getData).
|
||||
*/
|
||||
public final String getNodeValue()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Assigns the data associated with the processing instruction;
|
||||
* same as setNodeValue.
|
||||
*/
|
||||
public final void setData(String data)
|
||||
{
|
||||
setNodeValue(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Assigns the data associated with the processing instruction.
|
||||
*/
|
||||
public final void setNodeValue(String data)
|
||||
{
|
||||
if (isReadonly())
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/* DomText.java --
|
||||
Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
/**
|
||||
* <p> "Text" implementation. </p>
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomText
|
||||
extends DomCharacterData
|
||||
implements Text
|
||||
{
|
||||
|
||||
// NOTE: deleted unused per-instance "isIgnorable"
|
||||
// support to reclaim its space.
|
||||
|
||||
/**
|
||||
* Constructs a text node associated with the specified
|
||||
* document and holding the specified data.
|
||||
*
|
||||
* <p>This constructor should only be invoked by a Document object
|
||||
* as part of its createTextNode functionality, or through a subclass
|
||||
* which is similarly used in a "Sub-DOM" style layer.
|
||||
*/
|
||||
protected DomText(DomDocument owner, String value)
|
||||
{
|
||||
super(TEXT_NODE, owner, value);
|
||||
}
|
||||
|
||||
protected DomText(DomDocument owner, char[] buf, int off, int len)
|
||||
{
|
||||
super(TEXT_NODE, owner, buf, off, len);
|
||||
}
|
||||
|
||||
// Used by DomCDATA
|
||||
DomText(short nodeType, DomDocument owner, String value)
|
||||
{
|
||||
super(nodeType, owner, value);
|
||||
}
|
||||
|
||||
DomText(short nodeType, DomDocument owner, char[] buf, int off, int len)
|
||||
{
|
||||
super(nodeType, owner, buf, off, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Returns the string "#text".
|
||||
*/
|
||||
// can't be 'final' with CDATA subclassing
|
||||
public String getNodeName()
|
||||
{
|
||||
return "#text";
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>DOM L1</b>
|
||||
* Splits this text node in two parts at the offset, returning
|
||||
* the new text node (the sibling with the second part).
|
||||
*/
|
||||
public Text splitText(int offset)
|
||||
{
|
||||
if (isReadonly())
|
||||
{
|
||||
throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
|
||||
}
|
||||
try
|
||||
{
|
||||
String text = getNodeValue();
|
||||
String before = text.substring(0, offset);
|
||||
String after = text.substring(offset);
|
||||
Text next;
|
||||
|
||||
if (getNodeType() == TEXT_NODE)
|
||||
{
|
||||
next = owner.createTextNode(after);
|
||||
}
|
||||
else // CDATA_SECTION_NODE
|
||||
{
|
||||
next = owner.createCDATASection(after);
|
||||
}
|
||||
|
||||
if (this.next != null)
|
||||
{
|
||||
parent.insertBefore(next, this.next);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(next);
|
||||
}
|
||||
setNodeValue(before);
|
||||
return next;
|
||||
|
||||
}
|
||||
catch (IndexOutOfBoundsException x)
|
||||
{
|
||||
throw new DomEx(DomEx.INDEX_SIZE_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
// DOM Level 3
|
||||
|
||||
public boolean isElementContentWhitespace()
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
DomDoctype doctype = (DomDoctype) owner.getDoctype();
|
||||
if (doctype != null)
|
||||
{
|
||||
DTDElementTypeInfo info =
|
||||
doctype.getElementTypeInfo(parent.getNodeName());
|
||||
if (info != null)
|
||||
{
|
||||
if (info.model == null && info.model.indexOf("#PCDATA") != -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return getNodeValue().trim().length() == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getWholeText()
|
||||
{
|
||||
DomNode ref = this;
|
||||
DomNode ctx;
|
||||
for (ctx = previous; ctx != null &&
|
||||
(ctx.nodeType == TEXT_NODE || ctx.nodeType == CDATA_SECTION_NODE);
|
||||
ctx = ctx.previous)
|
||||
{
|
||||
ref = ctx;
|
||||
}
|
||||
StringBuffer buf = new StringBuffer(ref.getNodeValue());
|
||||
for (ctx = ref.next; ctx != null &&
|
||||
(ctx.nodeType == TEXT_NODE || ctx.nodeType == CDATA_SECTION_NODE);
|
||||
ctx = ctx.next)
|
||||
{
|
||||
buf.append(ctx.getNodeValue());
|
||||
}
|
||||
return buf.toString ();
|
||||
}
|
||||
|
||||
public Text replaceWholeText(String content)
|
||||
throws DOMException
|
||||
{
|
||||
boolean isEmpty = (content == null || content.length () == 0);
|
||||
if (!isEmpty)
|
||||
{
|
||||
setNodeValue(content);
|
||||
}
|
||||
|
||||
DomNode ref = this;
|
||||
DomNode ctx;
|
||||
for (ctx = previous; ctx != null &&
|
||||
(ctx.nodeType == TEXT_NODE || ctx.nodeType == CDATA_SECTION_NODE);
|
||||
ctx = ctx.previous)
|
||||
{
|
||||
ref = ctx;
|
||||
}
|
||||
ctx = ref.next;
|
||||
if ((isEmpty || ref != this) && parent != null)
|
||||
{
|
||||
parent.removeChild(ref);
|
||||
}
|
||||
for (; ctx != null &&
|
||||
(ctx.nodeType == TEXT_NODE || ctx.nodeType == CDATA_SECTION_NODE);
|
||||
ctx = ref)
|
||||
{
|
||||
ref = ctx.next;
|
||||
if ((isEmpty || ctx != this) && parent != null)
|
||||
{
|
||||
parent.removeChild(ctx);
|
||||
}
|
||||
}
|
||||
return (isEmpty) ? null : this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/* DomXPathExpression.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpression;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.xpath.XPathException;
|
||||
import org.w3c.dom.xpath.XPathNSResolver;
|
||||
import org.w3c.dom.xpath.XPathResult;
|
||||
import gnu.xml.xpath.DocumentOrderComparator;
|
||||
|
||||
/**
|
||||
* An XPath expression.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DomXPathExpression
|
||||
implements org.w3c.dom.xpath.XPathExpression
|
||||
{
|
||||
|
||||
final DomDocument doc;
|
||||
final XPathExpression expression;
|
||||
final XPathNSResolver resolver;
|
||||
|
||||
DomXPathExpression(DomDocument doc, String expression,
|
||||
XPathNSResolver resolver)
|
||||
throws XPathException
|
||||
{
|
||||
this.doc = doc;
|
||||
this.resolver = resolver;
|
||||
|
||||
XPathFactory factory = XPathFactory.newInstance();
|
||||
XPath xpath = factory.newXPath();
|
||||
if (resolver != null)
|
||||
{
|
||||
xpath.setNamespaceContext(new DomNSResolverContext(resolver));
|
||||
}
|
||||
try
|
||||
{
|
||||
this.expression = xpath.compile(expression);
|
||||
}
|
||||
catch (XPathExpressionException e)
|
||||
{
|
||||
throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,
|
||||
e.getMessage ());
|
||||
}
|
||||
}
|
||||
|
||||
public Object evaluate(Node contextNode, short type, Object result)
|
||||
throws XPathException, DOMException
|
||||
{
|
||||
try
|
||||
{
|
||||
QName typeName = null;
|
||||
switch (type)
|
||||
{
|
||||
case XPathResult.BOOLEAN_TYPE:
|
||||
typeName = XPathConstants.BOOLEAN;
|
||||
break;
|
||||
case XPathResult.NUMBER_TYPE:
|
||||
typeName = XPathConstants.NUMBER;
|
||||
break;
|
||||
case XPathResult.STRING_TYPE:
|
||||
typeName = XPathConstants.STRING;
|
||||
break;
|
||||
case XPathResult.ANY_UNORDERED_NODE_TYPE:
|
||||
case XPathResult.FIRST_ORDERED_NODE_TYPE:
|
||||
typeName = XPathConstants.NODE;
|
||||
break;
|
||||
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
|
||||
case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
|
||||
typeName = XPathConstants.NODESET;
|
||||
break;
|
||||
default:
|
||||
throw new XPathException(XPathException.TYPE_ERR, null);
|
||||
}
|
||||
Object val = expression.evaluate(contextNode, typeName);
|
||||
switch (type)
|
||||
{
|
||||
case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
|
||||
// Sort the nodes
|
||||
List ns = new ArrayList((Collection) val);
|
||||
Collections.sort(ns, new DocumentOrderComparator());
|
||||
val = ns;
|
||||
}
|
||||
return new DomXPathResult(val, type);
|
||||
}
|
||||
catch (javax.xml.xpath.XPathException e)
|
||||
{
|
||||
throw new XPathException(XPathException.TYPE_ERR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return getClass ().getName () + "[expression=" + expression + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/* DomXPathNSResolver.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.xpath.XPathNSResolver;
|
||||
|
||||
/**
|
||||
* Generic XPath namespace resolver using a DOM Node.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DomXPathNSResolver
|
||||
implements XPathNSResolver
|
||||
{
|
||||
|
||||
Node node;
|
||||
|
||||
DomXPathNSResolver (Node node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public String lookupNamespaceURI (String prefix)
|
||||
{
|
||||
return node.lookupNamespaceURI (prefix);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/* DomXPathResult.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.xpath.XPathException;
|
||||
import org.w3c.dom.xpath.XPathNSResolver;
|
||||
import org.w3c.dom.xpath.XPathResult;
|
||||
|
||||
/**
|
||||
* An XPath result object.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DomXPathResult
|
||||
implements XPathResult
|
||||
{
|
||||
|
||||
final Object value;
|
||||
final short type;
|
||||
Iterator iterator;
|
||||
|
||||
DomXPathResult (Object value, short requestedType)
|
||||
{
|
||||
this.value = value;
|
||||
if (value instanceof Boolean)
|
||||
{
|
||||
type = XPathResult.BOOLEAN_TYPE;
|
||||
}
|
||||
else if (value instanceof Double)
|
||||
{
|
||||
type = XPathResult.NUMBER_TYPE;
|
||||
}
|
||||
else if (value instanceof String)
|
||||
{
|
||||
type = XPathResult.STRING_TYPE;
|
||||
}
|
||||
else if (value instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) value;
|
||||
switch (requestedType)
|
||||
{
|
||||
case XPathResult.ANY_TYPE:
|
||||
case XPathResult.ANY_UNORDERED_NODE_TYPE:
|
||||
type = (ns.size () == 1) ? XPathResult.FIRST_ORDERED_NODE_TYPE :
|
||||
XPathResult.ORDERED_NODE_ITERATOR_TYPE;
|
||||
break;
|
||||
default:
|
||||
type = requestedType;
|
||||
}
|
||||
iterator = ns.iterator ();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException ();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getBooleanValue()
|
||||
{
|
||||
if (type == XPathResult.BOOLEAN_TYPE)
|
||||
{
|
||||
return ((Boolean) value).booleanValue ();
|
||||
}
|
||||
throw new XPathException (XPathException.TYPE_ERR, value.toString ());
|
||||
}
|
||||
|
||||
public boolean getInvalidIteratorState()
|
||||
{
|
||||
return iterator == null;
|
||||
}
|
||||
|
||||
public double getNumberValue()
|
||||
{
|
||||
if (type == XPathResult.NUMBER_TYPE)
|
||||
{
|
||||
return ((Double) value).doubleValue ();
|
||||
}
|
||||
throw new XPathException (XPathException.TYPE_ERR, value.toString ());
|
||||
}
|
||||
|
||||
public short getResultType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public Node getSingleNodeValue()
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case XPathResult.FIRST_ORDERED_NODE_TYPE:
|
||||
case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
|
||||
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
|
||||
Collection ns = (Collection) value;
|
||||
if (ns.isEmpty ())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (Node) ns.iterator ().next ();
|
||||
}
|
||||
}
|
||||
throw new XPathException (XPathException.TYPE_ERR, value.toString ());
|
||||
}
|
||||
|
||||
public int getSnapshotLength()
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case XPathResult.FIRST_ORDERED_NODE_TYPE:
|
||||
case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
|
||||
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
|
||||
return ((Collection) value).size ();
|
||||
}
|
||||
throw new XPathException (XPathException.TYPE_ERR, value.toString ());
|
||||
}
|
||||
|
||||
public String getStringValue()
|
||||
{
|
||||
if (type == XPathResult.STRING_TYPE)
|
||||
{
|
||||
return (String) value;
|
||||
}
|
||||
throw new XPathException (XPathException.TYPE_ERR, value.toString ());
|
||||
}
|
||||
|
||||
public Node iterateNext()
|
||||
{
|
||||
if (iterator != null)
|
||||
{
|
||||
if (iterator.hasNext ())
|
||||
{
|
||||
return (Node) iterator.next ();
|
||||
}
|
||||
else
|
||||
{
|
||||
iterator = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
throw new XPathException (XPathException.TYPE_ERR, value.toString ());
|
||||
}
|
||||
|
||||
public Node snapshotItem(int index)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case XPathResult.FIRST_ORDERED_NODE_TYPE:
|
||||
case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
|
||||
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
|
||||
case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
|
||||
Collection ns = (Collection) value;
|
||||
Node[] nodes = new Node[ns.size ()];
|
||||
ns.toArray (nodes);
|
||||
return nodes[index];
|
||||
}
|
||||
throw new XPathException (XPathException.TYPE_ERR, value.toString ());
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return getClass ().getName () + "[type=" + typeName (type) + ",value=" +
|
||||
value + ']';
|
||||
}
|
||||
|
||||
private String typeName (short type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case XPathResult.BOOLEAN_TYPE:
|
||||
return "BOOLEAN_TYPE";
|
||||
case XPathResult.NUMBER_TYPE:
|
||||
return "NUMBER_TYPE";
|
||||
case XPathResult.STRING_TYPE:
|
||||
return "STRING_TYPE";
|
||||
case XPathResult.FIRST_ORDERED_NODE_TYPE:
|
||||
return "FIRST_ORDERED_NODE_TYPE";
|
||||
case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
|
||||
return "ORDERED_NODE_ITERATOR_TYPE";
|
||||
case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
|
||||
return "ORDERED_NODE_SNAPSHOT_TYPE";
|
||||
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
|
||||
return "UNORDERED_NODE_ITERATOR_TYPE";
|
||||
case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
|
||||
return "UNORDERED_NODE_SNAPSHOT_TYPE";
|
||||
default:
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* ImplementationList.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc..
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.DOMImplementationList;
|
||||
|
||||
/**
|
||||
* Implementation list for GNU JAXP.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class ImplementationList
|
||||
implements DOMImplementationList
|
||||
{
|
||||
|
||||
private List list;
|
||||
|
||||
ImplementationList(List list)
|
||||
{
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public DOMImplementation item(int index)
|
||||
{
|
||||
return (DOMImplementation) list.get(index);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/* ImplementationSource.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc..
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.DOMImplementationList;
|
||||
import org.w3c.dom.DOMImplementationSource;
|
||||
|
||||
/**
|
||||
* Implementation source for GNU JAXP.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class ImplementationSource
|
||||
implements DOMImplementationSource
|
||||
{
|
||||
|
||||
private static final String DIGITS = "1234567890";
|
||||
|
||||
/*
|
||||
* GNU DOM implementations.
|
||||
*/
|
||||
private static final DOMImplementation[] implementations;
|
||||
|
||||
static
|
||||
{
|
||||
List acc = new ArrayList();
|
||||
acc.add(new gnu.xml.dom.DomImpl());
|
||||
try
|
||||
{
|
||||
Class t = Class.forName("gnu.xml.libxmlj.dom.GnomeDocumentBuilder");
|
||||
acc.add(t.newInstance());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// libxmlj not available
|
||||
}
|
||||
catch (UnsatisfiedLinkError e)
|
||||
{
|
||||
// libxmlj not available
|
||||
}
|
||||
implementations = new DOMImplementation[acc.size()];
|
||||
acc.toArray(implementations);
|
||||
}
|
||||
|
||||
public DOMImplementation getDOMImplementation(String features)
|
||||
{
|
||||
List available = getImplementations(features);
|
||||
if (available.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return (DOMImplementation) available.get(0);
|
||||
}
|
||||
|
||||
public DOMImplementationList getDOMImplementationList(String features)
|
||||
{
|
||||
List available = getImplementations(features);
|
||||
return new ImplementationList(available);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the implementations that support the specified
|
||||
* features.
|
||||
*/
|
||||
private final List getImplementations(String features)
|
||||
{
|
||||
List available = new ArrayList(Arrays.asList(implementations));
|
||||
for (Iterator i = parseFeatures(features).iterator(); i.hasNext(); )
|
||||
{
|
||||
String feature = (String) i.next();
|
||||
String version = null;
|
||||
int si = feature.indexOf(' ');
|
||||
if (si != -1)
|
||||
{
|
||||
version = feature.substring(si + 1);
|
||||
feature = feature.substring(0, si);
|
||||
}
|
||||
for (Iterator j = available.iterator(); j.hasNext(); )
|
||||
{
|
||||
DOMImplementation impl = (DOMImplementation) j.next();
|
||||
if (!impl.hasFeature(feature, version))
|
||||
{
|
||||
j.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
return available;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the feature list into feature tokens.
|
||||
*/
|
||||
final List parseFeatures(String features)
|
||||
{
|
||||
List list = new ArrayList();
|
||||
int pos = 0, start = 0;
|
||||
int len = features.length();
|
||||
for (; pos < len; pos++)
|
||||
{
|
||||
char c = features.charAt(pos);
|
||||
if (c == ' ')
|
||||
{
|
||||
if (pos + 1 < len &&
|
||||
DIGITS.indexOf(features.charAt(pos + 1)) == -1)
|
||||
{
|
||||
list.add(getFeature(features, start, pos));
|
||||
start = pos + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pos > start)
|
||||
{
|
||||
list.add(getFeature(features, start, len));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
final String getFeature(String features, int start, int end)
|
||||
{
|
||||
if (features.length() > 0 && features.charAt(start) == '+')
|
||||
{
|
||||
return features.substring(start + 1, end);
|
||||
}
|
||||
return features.substring(start, end);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/* JAXPFactory.java --
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
|
||||
/**
|
||||
* DOM bootstrapping API, for use with JAXP.
|
||||
*
|
||||
* @see Consumer
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public final class JAXPFactory
|
||||
extends DocumentBuilderFactory
|
||||
{
|
||||
|
||||
private static final String PROPERTY = "http://xml.org/sax/properties/";
|
||||
private static final String FEATURE = "http://xml.org/sax/features/";
|
||||
|
||||
private SAXParserFactory pf;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public JAXPFactory()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a JAXP document builder which uses the default
|
||||
* JAXP SAX2 parser and the DOM implementation in this package.
|
||||
*/
|
||||
public DocumentBuilder newDocumentBuilder()
|
||||
throws ParserConfigurationException
|
||||
{
|
||||
if (pf == null)
|
||||
{
|
||||
// Force use of AElfred2 since not all JAXP parsers
|
||||
// conform very well to the SAX2 API spec ...
|
||||
pf = new gnu.xml.aelfred2.JAXPFactory();
|
||||
// pf = SAXParserFactory.newInstance ();
|
||||
}
|
||||
|
||||
// JAXP default: false
|
||||
pf.setValidating(isValidating());
|
||||
|
||||
// FIXME: this namespace setup may cause errors in some
|
||||
// conformant SAX2 parsers, which we CAN patch up by
|
||||
// splicing a "NSFilter" stage up front ...
|
||||
|
||||
// JAXP default: false
|
||||
pf.setNamespaceAware(isNamespaceAware());
|
||||
|
||||
try
|
||||
{
|
||||
// undo rude "namespace-prefixes=false" default
|
||||
pf.setFeature(FEATURE + "namespace-prefixes", true);
|
||||
|
||||
return new JAXPBuilder(pf.newSAXParser().getXMLReader(), this);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
String msg = "can't create JAXP DocumentBuilder: " + e.getMessage();
|
||||
throw new ParserConfigurationException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/** There seems to be no useful specification for attribute names */
|
||||
public void setAttribute(String name, Object value)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
if ("http://java.sun.com/xml/jaxp/properties/schemaLanguage".equals(name))
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException(name);
|
||||
}
|
||||
}
|
||||
|
||||
/** There seems to be no useful specification for attribute names */
|
||||
public Object getAttribute(String name)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
throw new IllegalArgumentException(name);
|
||||
}
|
||||
|
||||
static final class JAXPBuilder
|
||||
extends DocumentBuilder
|
||||
implements ErrorHandler
|
||||
{
|
||||
|
||||
private Consumer consumer;
|
||||
private XMLReader producer;
|
||||
private DomImpl impl;
|
||||
|
||||
JAXPBuilder(XMLReader parser, JAXPFactory factory)
|
||||
throws ParserConfigurationException
|
||||
{
|
||||
impl = new DomImpl();
|
||||
|
||||
// set up consumer side
|
||||
try
|
||||
{
|
||||
consumer = new Consumer();
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
throw new ParserConfigurationException(e.getMessage());
|
||||
}
|
||||
|
||||
// JAXP defaults: true, noise nodes are good (bleech)
|
||||
consumer.setHidingReferences(factory.isExpandEntityReferences());
|
||||
consumer.setHidingComments(factory.isIgnoringComments());
|
||||
consumer.setHidingWhitespace(factory.isIgnoringElementContentWhitespace());
|
||||
consumer.setHidingCDATA(factory.isCoalescing());
|
||||
|
||||
// set up producer side
|
||||
producer = parser;
|
||||
producer.setContentHandler(consumer.getContentHandler());
|
||||
producer.setDTDHandler(consumer.getDTDHandler());
|
||||
|
||||
try
|
||||
{
|
||||
String id;
|
||||
|
||||
// if validating, report validity errors, and default
|
||||
// to treating them as fatal
|
||||
if (factory.isValidating ())
|
||||
{
|
||||
producer.setFeature(FEATURE + "validation", true);
|
||||
producer.setErrorHandler(this);
|
||||
}
|
||||
|
||||
// always save prefix info, maybe do namespace processing
|
||||
producer.setFeature(FEATURE + "namespace-prefixes", true);
|
||||
producer.setFeature(FEATURE + "namespaces",
|
||||
factory.isNamespaceAware());
|
||||
|
||||
// set important handlers
|
||||
id = PROPERTY + "lexical-handler";
|
||||
producer.setProperty(id, consumer.getProperty(id));
|
||||
|
||||
id = PROPERTY + "declaration-handler";
|
||||
producer.setProperty(id, consumer.getProperty(id));
|
||||
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
throw new ParserConfigurationException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Document parse(InputSource source)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
producer.parse(source);
|
||||
Document doc = consumer.getDocument();
|
||||
// TODO inputEncoding
|
||||
doc.setDocumentURI(source.getSystemId());
|
||||
return doc;
|
||||
}
|
||||
|
||||
public boolean isNamespaceAware()
|
||||
{
|
||||
try
|
||||
{
|
||||
return producer.getFeature(FEATURE + "namespaces");
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
// "can't happen"
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isValidating()
|
||||
{
|
||||
try
|
||||
{
|
||||
return producer.getFeature(FEATURE + "validation");
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
// "can't happen"
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setEntityResolver(EntityResolver resolver)
|
||||
{
|
||||
producer.setEntityResolver(resolver);
|
||||
}
|
||||
|
||||
public void setErrorHandler(ErrorHandler handler)
|
||||
{
|
||||
producer.setErrorHandler(handler);
|
||||
consumer.setErrorHandler(handler);
|
||||
}
|
||||
|
||||
public DOMImplementation getDOMImplementation()
|
||||
{
|
||||
return impl;
|
||||
}
|
||||
|
||||
public Document newDocument()
|
||||
{
|
||||
return new DomDocument();
|
||||
}
|
||||
|
||||
// implementation of error handler that's used when validating
|
||||
public void fatalError(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
public void error(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
public void warning(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/* DomLSEx.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import org.w3c.dom.ls.LSException;
|
||||
|
||||
/**
|
||||
* A DOM LS exception incorporating a cause.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomLSEx
|
||||
extends LSException
|
||||
{
|
||||
|
||||
private final Exception cause2;
|
||||
|
||||
public DomLSEx(short type, Exception cause)
|
||||
{
|
||||
super(type, cause.getMessage());
|
||||
cause2 = cause;
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintStream out)
|
||||
{
|
||||
super.printStackTrace(out);
|
||||
out.print("caused by ");
|
||||
cause2.printStackTrace(out);
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintWriter out)
|
||||
{
|
||||
super.printStackTrace(out);
|
||||
out.print("caused by ");
|
||||
cause2.printStackTrace(out);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/* DomLSInput.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import org.w3c.dom.ls.LSInput;
|
||||
|
||||
/**
|
||||
* Specification of XML input to parse.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomLSInput
|
||||
implements LSInput
|
||||
{
|
||||
|
||||
private InputStream in;
|
||||
private String systemId;
|
||||
private String publicId;
|
||||
private String baseURI;
|
||||
private String encoding;
|
||||
private boolean certifiedText;
|
||||
|
||||
public Reader getCharacterStream()
|
||||
{
|
||||
return new InputStreamReader(in);
|
||||
}
|
||||
|
||||
public void setCharacterStream(Reader characterStream)
|
||||
{
|
||||
in = new ReaderInputStream(characterStream);
|
||||
}
|
||||
|
||||
public InputStream getByteStream()
|
||||
{
|
||||
return in;
|
||||
}
|
||||
|
||||
public void setByteStream(InputStream byteStream)
|
||||
{
|
||||
in = byteStream;
|
||||
}
|
||||
|
||||
public String getStringData()
|
||||
{
|
||||
StringBuffer acc = new StringBuffer();
|
||||
Reader reader = getCharacterStream();
|
||||
try
|
||||
{
|
||||
char[] buf = new char[4096];
|
||||
for (int len = reader.read(buf); len != -1; len = reader.read(buf))
|
||||
{
|
||||
acc.append(buf, 0, len);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return null; // ?
|
||||
}
|
||||
return acc.toString();
|
||||
}
|
||||
|
||||
public void setStringData(String stringData)
|
||||
{
|
||||
in = new ReaderInputStream(new StringReader(stringData));
|
||||
}
|
||||
|
||||
public String getSystemId()
|
||||
{
|
||||
return systemId;
|
||||
}
|
||||
|
||||
public void setSystemId(String systemId)
|
||||
{
|
||||
this.systemId = systemId;
|
||||
}
|
||||
|
||||
public String getPublicId()
|
||||
{
|
||||
return publicId;
|
||||
}
|
||||
|
||||
public void setPublicId(String publicId)
|
||||
{
|
||||
this.publicId = publicId;
|
||||
}
|
||||
|
||||
public String getBaseURI()
|
||||
{
|
||||
return baseURI;
|
||||
}
|
||||
|
||||
public void setBaseURI(String baseURI)
|
||||
{
|
||||
this.baseURI = baseURI;
|
||||
}
|
||||
|
||||
public String getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public boolean getCertifiedText()
|
||||
{
|
||||
return certifiedText;
|
||||
}
|
||||
|
||||
public void setCertifiedText(boolean certifiedText)
|
||||
{
|
||||
this.certifiedText = certifiedText;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/* DomLSOutput.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import org.w3c.dom.ls.LSOutput;
|
||||
|
||||
/**
|
||||
* Specification of XML output to produce.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomLSOutput
|
||||
implements LSOutput
|
||||
{
|
||||
|
||||
private OutputStream out;
|
||||
private String systemId;
|
||||
private String encoding;
|
||||
|
||||
public Writer getCharacterStream()
|
||||
{
|
||||
return new OutputStreamWriter(out);
|
||||
}
|
||||
|
||||
public void setCharacterStream(Writer characterStream)
|
||||
{
|
||||
out = new WriterOutputStream(characterStream);
|
||||
}
|
||||
|
||||
public OutputStream getByteStream()
|
||||
{
|
||||
return out;
|
||||
}
|
||||
|
||||
public void setByteStream(OutputStream out)
|
||||
{
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public String getSystemId()
|
||||
{
|
||||
return systemId;
|
||||
}
|
||||
|
||||
public void setSystemId(String systemId)
|
||||
{
|
||||
this.systemId = systemId;
|
||||
}
|
||||
|
||||
public String getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,574 @@
|
||||
/* DomLSParser.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DOMConfiguration;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.DOMStringList;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.ls.DOMImplementationLS;
|
||||
import org.w3c.dom.ls.LSException;
|
||||
import org.w3c.dom.ls.LSInput;
|
||||
import org.w3c.dom.ls.LSParser;
|
||||
import org.w3c.dom.ls.LSParserFilter;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import gnu.xml.dom.DomDocument;
|
||||
import gnu.xml.dom.DomEx;
|
||||
|
||||
/**
|
||||
* Parser implementation for GNU DOM.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomLSParser
|
||||
implements LSParser, DOMConfiguration, DOMStringList, ErrorHandler
|
||||
{
|
||||
|
||||
private static final List SUPPORTED_PARAMETERS
|
||||
= Arrays.asList(new String[] { "cdata-sections",
|
||||
"comments",
|
||||
"element-content-whitespace",
|
||||
"namespaces",
|
||||
"expand-entity-references",
|
||||
"coalescing",
|
||||
"validating",
|
||||
"xinclude-aware",
|
||||
"entity-resolver",
|
||||
"error-handler" });
|
||||
|
||||
private LSParserFilter filter;
|
||||
private final boolean async;
|
||||
private String schemaType;
|
||||
private SAXEventSink eventSink;
|
||||
private SAXParserFactory factory;
|
||||
private XMLReader reader;
|
||||
|
||||
private boolean namespaceAware = true;
|
||||
private boolean ignoreWhitespace;
|
||||
private boolean expandEntityReferences;
|
||||
private boolean ignoreComments;
|
||||
private boolean coalescing;
|
||||
private boolean validating;
|
||||
private boolean xIncludeAware;
|
||||
private EntityResolver entityResolver;
|
||||
private ErrorHandler errorHandler;
|
||||
|
||||
public DomLSParser(short mode, String schemaType)
|
||||
throws DOMException
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case DOMImplementationLS.MODE_ASYNCHRONOUS:
|
||||
async = true;
|
||||
break;
|
||||
case DOMImplementationLS.MODE_SYNCHRONOUS:
|
||||
async = false;
|
||||
break;
|
||||
default:
|
||||
throw new DomEx(DOMException.NOT_SUPPORTED_ERR);
|
||||
}
|
||||
// TODO schemaType
|
||||
this.schemaType = schemaType;
|
||||
factory = SAXParserFactory.newInstance();
|
||||
}
|
||||
|
||||
// -- LSParser --
|
||||
|
||||
public DOMConfiguration getDomConfig()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public LSParserFilter getFilter()
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
|
||||
public void setFilter(LSParserFilter filter)
|
||||
{
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public boolean getAsync()
|
||||
{
|
||||
return async;
|
||||
}
|
||||
|
||||
public boolean getBusy()
|
||||
{
|
||||
return eventSink != null;
|
||||
}
|
||||
|
||||
public Document parse(LSInput input)
|
||||
throws DOMException, LSException
|
||||
{
|
||||
if (async)
|
||||
{
|
||||
return doParse(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
return doParse(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Document parseURI(String uri)
|
||||
throws DOMException, LSException
|
||||
{
|
||||
LSInput input = new DomLSInput();
|
||||
input.setSystemId(uri);
|
||||
return parse(input);
|
||||
}
|
||||
|
||||
public Node parseWithContext(LSInput input, Node context, short action)
|
||||
throws DOMException, LSException
|
||||
{
|
||||
Document doc = (context.getNodeType() == Node.DOCUMENT_NODE) ?
|
||||
(Document) context : context.getOwnerDocument();
|
||||
input.setBaseURI(doc.getDocumentURI());
|
||||
// TODO use namespaces defined on context node
|
||||
Document ret = parse(input);
|
||||
Node root = ret.getDocumentElement();
|
||||
root = doc.adoptNode(root);
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_APPEND_AS_CHILDREN:
|
||||
context.appendChild(root);
|
||||
break;
|
||||
case ACTION_REPLACE_CHILDREN:
|
||||
Node c1 = context.getFirstChild();
|
||||
while (c1 != null)
|
||||
{
|
||||
Node next = c1.getNextSibling();
|
||||
context.removeChild(c1);
|
||||
c1 = next;
|
||||
}
|
||||
context.appendChild(root);
|
||||
break;
|
||||
case ACTION_INSERT_BEFORE:
|
||||
Node p1 = context.getParentNode();
|
||||
p1.insertBefore(root, context);
|
||||
break;
|
||||
case ACTION_INSERT_AFTER:
|
||||
Node p2 = context.getParentNode();
|
||||
Node r1 = context.getNextSibling();
|
||||
if (r1 == null)
|
||||
{
|
||||
p2.appendChild(root);
|
||||
}
|
||||
else
|
||||
{
|
||||
p2.insertBefore(root, r1);
|
||||
}
|
||||
break;
|
||||
case ACTION_REPLACE:
|
||||
Node p3 = context.getParentNode();
|
||||
Node r2 = context.getNextSibling();
|
||||
p3.removeChild(context);
|
||||
if (r2 == null)
|
||||
{
|
||||
p3.appendChild(root);
|
||||
}
|
||||
else
|
||||
{
|
||||
p3.insertBefore(root, r2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
public void abort()
|
||||
{
|
||||
if (eventSink != null)
|
||||
{
|
||||
eventSink.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private Document doParse(LSInput input)
|
||||
throws DOMException, LSException
|
||||
{
|
||||
// create event sink
|
||||
if (eventSink != null)
|
||||
{
|
||||
throw new LSException(LSException.PARSE_ERR, "parse in progress");
|
||||
}
|
||||
InputSource source = getInputSource(input);
|
||||
eventSink = (filter == null) ? new SAXEventSink() :
|
||||
new FilteredSAXEventSink(filter);
|
||||
// configure sink
|
||||
eventSink.namespaceAware = namespaceAware;
|
||||
eventSink.ignoreWhitespace = ignoreWhitespace;
|
||||
eventSink.expandEntityReferences = expandEntityReferences;
|
||||
eventSink.ignoreComments = ignoreComments;
|
||||
eventSink.coalescing = coalescing;
|
||||
// get and configure reader
|
||||
XMLReader reader = getXMLReader();
|
||||
try
|
||||
{
|
||||
reader.setContentHandler(eventSink);
|
||||
reader.setDTDHandler(eventSink);
|
||||
reader.setProperty("http://xml.org/sax/properties/lexical-handler",
|
||||
eventSink);
|
||||
reader.setProperty("http://xml.org/sax/properties/declaration-handler",
|
||||
eventSink);
|
||||
reader.setFeature("http://xml.org/sax/features/namespaces",
|
||||
namespaceAware);
|
||||
reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
|
||||
true);
|
||||
reader.setFeature("http://xml.org/sax/features/validation",
|
||||
validating);
|
||||
try
|
||||
{
|
||||
reader.setFeature("http://xml.org/sax/features/use-attributes2",
|
||||
true);
|
||||
}
|
||||
catch (SAXNotRecognizedException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
try
|
||||
{
|
||||
reader.setFeature("http://xml.org/sax/features/external-general-entities",
|
||||
true);
|
||||
}
|
||||
catch (SAXNotRecognizedException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
reader.setEntityResolver(entityResolver);
|
||||
reader.setErrorHandler(errorHandler);
|
||||
// parse
|
||||
reader.parse(source);
|
||||
}
|
||||
catch (DOMException e)
|
||||
{
|
||||
reader = null;
|
||||
eventSink = null;
|
||||
throw e;
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
reader = null;
|
||||
eventSink = null;
|
||||
throw new DomLSEx(LSException.PARSE_ERR, e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
reader = null;
|
||||
eventSink = null;
|
||||
throw new DomLSEx(LSException.PARSE_ERR, e);
|
||||
}
|
||||
// return document
|
||||
Document ret = eventSink.doc;
|
||||
String systemId = input.getSystemId();
|
||||
if (systemId != null && ret instanceof DomDocument)
|
||||
{
|
||||
((DomDocument) ret).setDocumentURI(systemId);
|
||||
}
|
||||
eventSink = null;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private XMLReader getXMLReader()
|
||||
throws LSException
|
||||
{
|
||||
if (reader == null)
|
||||
{
|
||||
factory.setNamespaceAware(namespaceAware);
|
||||
factory.setValidating(validating);
|
||||
factory.setXIncludeAware(xIncludeAware);
|
||||
try
|
||||
{
|
||||
SAXParser parser = factory.newSAXParser();
|
||||
reader = parser.getXMLReader();
|
||||
}
|
||||
catch (ParserConfigurationException e)
|
||||
{
|
||||
throw new DomLSEx(LSException.PARSE_ERR, e);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
throw new DomLSEx(LSException.PARSE_ERR, e);
|
||||
}
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
|
||||
private InputSource getInputSource(LSInput input)
|
||||
throws LSException
|
||||
{
|
||||
InputSource source = null;
|
||||
String systemId = input.getSystemId();
|
||||
InputStream in = input.getByteStream();
|
||||
if (in != null)
|
||||
{
|
||||
source = new InputSource(in);
|
||||
source.setSystemId(systemId);
|
||||
}
|
||||
if (source == null && entityResolver != null)
|
||||
{
|
||||
String publicId = input.getPublicId();
|
||||
try
|
||||
{
|
||||
source = entityResolver.resolveEntity(publicId, systemId);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
throw new DomLSEx(LSException.PARSE_ERR, e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new DomLSEx(LSException.PARSE_ERR, e);
|
||||
}
|
||||
}
|
||||
if (source == null)
|
||||
{
|
||||
URL url = null;
|
||||
String base = input.getBaseURI();
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
URL baseURL = (base == null) ? null : new URL(base);
|
||||
url = (baseURL == null) ? new URL(systemId) :
|
||||
new URL(baseURL, systemId);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
File baseFile = (base == null) ? null : new File(base);
|
||||
url = (baseFile == null) ? new File(systemId).toURL() :
|
||||
new File(baseFile, systemId).toURL();
|
||||
}
|
||||
in = url.openStream();
|
||||
systemId = url.toString();
|
||||
source = new InputSource(in);
|
||||
source.setSystemId(systemId);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new DomLSEx(LSException.PARSE_ERR, e);
|
||||
}
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
// -- DOMConfiguration --
|
||||
|
||||
public void setParameter(String name, Object value)
|
||||
throws DOMException
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
if ("cdata-sections".equals(name))
|
||||
{
|
||||
coalescing = !((Boolean) value).booleanValue();
|
||||
}
|
||||
else if ("comments".equals(name))
|
||||
{
|
||||
ignoreComments = !((Boolean) value).booleanValue();
|
||||
}
|
||||
else if ("element-content-whitespace".equals(name))
|
||||
{
|
||||
ignoreWhitespace = !((Boolean) value).booleanValue();
|
||||
}
|
||||
else if ("namespaces".equals(name))
|
||||
{
|
||||
namespaceAware = ((Boolean) value).booleanValue();
|
||||
}
|
||||
else if ("expand-entity-references".equals(name))
|
||||
{
|
||||
expandEntityReferences = ((Boolean) value).booleanValue();
|
||||
}
|
||||
else if ("coalescing".equals(name))
|
||||
{
|
||||
coalescing = ((Boolean) value).booleanValue();
|
||||
}
|
||||
else if ("validating".equals(name))
|
||||
{
|
||||
validating = ((Boolean) value).booleanValue();
|
||||
}
|
||||
else if ("xinclude-aware".equals(name))
|
||||
{
|
||||
xIncludeAware = ((Boolean) value).booleanValue();
|
||||
}
|
||||
else if ("entity-resolver".equals(name))
|
||||
{
|
||||
entityResolver = (EntityResolver) value;
|
||||
}
|
||||
else if ("error-handler".equals(name))
|
||||
{
|
||||
errorHandler = (ErrorHandler) value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_SUPPORTED_ERR);
|
||||
}
|
||||
// invalidate reader, a new one will be created
|
||||
reader = null;
|
||||
}
|
||||
|
||||
public Object getParameter(String name)
|
||||
throws DOMException
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
if ("cdata-sections".equals(name))
|
||||
{
|
||||
return coalescing ? Boolean.FALSE : Boolean.TRUE;
|
||||
}
|
||||
else if ("comments".equals(name))
|
||||
{
|
||||
return ignoreComments ? Boolean.FALSE : Boolean.TRUE;
|
||||
}
|
||||
else if ("element-content-whitespace".equals(name))
|
||||
{
|
||||
return ignoreWhitespace ? Boolean.FALSE : Boolean.TRUE;
|
||||
}
|
||||
else if ("namespaces".equals(name))
|
||||
{
|
||||
return namespaceAware ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("expand-entity-references".equals(name))
|
||||
{
|
||||
return expandEntityReferences ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("coalescing".equals(name))
|
||||
{
|
||||
return coalescing ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("validating".equals(name))
|
||||
{
|
||||
return validating ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("xinclude-aware".equals(name))
|
||||
{
|
||||
return xIncludeAware ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
else if ("entity-resolver".equals(name))
|
||||
{
|
||||
return entityResolver;
|
||||
}
|
||||
else if ("error-handler".equals(name))
|
||||
{
|
||||
return errorHandler;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_SUPPORTED_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canSetParameter(String name, Object value)
|
||||
{
|
||||
return contains(name);
|
||||
}
|
||||
|
||||
public DOMStringList getParameterNames()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// -- DOMStringList --
|
||||
|
||||
public String item(int i)
|
||||
{
|
||||
return (String) SUPPORTED_PARAMETERS.get(i);
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
return SUPPORTED_PARAMETERS.size();
|
||||
}
|
||||
|
||||
public boolean contains(String str)
|
||||
{
|
||||
return SUPPORTED_PARAMETERS.contains(str);
|
||||
}
|
||||
|
||||
// -- ErrorHandler --
|
||||
|
||||
public void warning(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
if (errorHandler != null)
|
||||
{
|
||||
errorHandler.warning(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void error(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
if (errorHandler != null)
|
||||
{
|
||||
errorHandler.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void fatalError(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
if (errorHandler != null)
|
||||
{
|
||||
errorHandler.fatalError(e);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
/* DomLSSerializer.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.w3c.dom.DOMConfiguration;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.DOMStringList;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.ls.LSException;
|
||||
import org.w3c.dom.ls.LSOutput;
|
||||
import org.w3c.dom.ls.LSSerializer;
|
||||
import org.w3c.dom.ls.LSSerializerFilter;
|
||||
import org.w3c.dom.traversal.NodeFilter;
|
||||
import gnu.xml.dom.DomEx;
|
||||
import gnu.xml.transform.StreamSerializer;
|
||||
|
||||
/**
|
||||
* Serialize a DOM node to a stream.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class DomLSSerializer
|
||||
extends StreamSerializer
|
||||
implements LSSerializer, DOMConfiguration, DOMStringList
|
||||
{
|
||||
|
||||
private static final List SUPPORTED_PARAMETERS =
|
||||
Arrays.asList(new String[] {"discard-default-content",
|
||||
"xml-declaration"});
|
||||
|
||||
private LSSerializerFilter filter;
|
||||
private StreamSerializer serializer;
|
||||
|
||||
public DomLSSerializer()
|
||||
{
|
||||
super();
|
||||
discardDefaultContent = true;
|
||||
}
|
||||
|
||||
// -- LSSerializer --
|
||||
|
||||
public DOMConfiguration getDomConfig()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getNewLine()
|
||||
{
|
||||
return eol;
|
||||
}
|
||||
|
||||
public void setNewLine(String newLine)
|
||||
{
|
||||
if (newLine == null)
|
||||
{
|
||||
newLine = System.getProperty("line.separator");
|
||||
}
|
||||
eol = newLine;
|
||||
}
|
||||
|
||||
public LSSerializerFilter getFilter()
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
|
||||
public void setFilter(LSSerializerFilter filter)
|
||||
{
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public boolean write(Node node, LSOutput output)
|
||||
throws LSException
|
||||
{
|
||||
OutputStream out = output.getByteStream();
|
||||
try
|
||||
{
|
||||
if (out == null)
|
||||
{
|
||||
String systemId = output.getSystemId();
|
||||
try
|
||||
{
|
||||
URL url = new URL(systemId);
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setDoOutput(true);
|
||||
if (connection instanceof HttpURLConnection)
|
||||
{
|
||||
((HttpURLConnection) connection).setRequestMethod("PUT");
|
||||
}
|
||||
out = connection.getOutputStream();
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
File file = new File(systemId);
|
||||
out = new FileOutputStream(file);
|
||||
}
|
||||
}
|
||||
serialize(node, out);
|
||||
out.flush();
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new DomLSEx(LSException.SERIALIZE_ERR, e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean writeToURI(Node node, String uri)
|
||||
throws LSException
|
||||
{
|
||||
LSOutput output = new DomLSOutput();
|
||||
output.setSystemId(uri);
|
||||
return write(node, output);
|
||||
}
|
||||
|
||||
public String writeToString(Node node)
|
||||
throws DOMException, LSException
|
||||
{
|
||||
Writer writer = new StringWriter();
|
||||
LSOutput output = new DomLSOutput();
|
||||
output.setCharacterStream(writer);
|
||||
write(node, output);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
public void serialize(Node node, OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (filter == null)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
int wts = filter.getWhatToShow();
|
||||
if (wts != NodeFilter.SHOW_ALL)
|
||||
{
|
||||
switch (node.getNodeType())
|
||||
{
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
if ((wts & NodeFilter.SHOW_ATTRIBUTE) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.TEXT_NODE:
|
||||
if ((wts & NodeFilter.SHOW_TEXT) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.ELEMENT_NODE:
|
||||
if ((wts & NodeFilter.SHOW_ELEMENT) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
if ((wts & NodeFilter.SHOW_CDATA_SECTION) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.COMMENT_NODE:
|
||||
if ((wts & NodeFilter.SHOW_COMMENT) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_NODE:
|
||||
if ((wts & NodeFilter.SHOW_DOCUMENT) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
if ((wts & NodeFilter.SHOW_DOCUMENT_TYPE) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
if ((wts & NodeFilter.SHOW_PROCESSING_INSTRUCTION) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
if ((wts & NodeFilter.SHOW_DOCUMENT_FRAGMENT) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.ENTITY_NODE:
|
||||
if ((wts & NodeFilter.SHOW_ENTITY) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
if ((wts & NodeFilter.SHOW_ENTITY_REFERENCE) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Node.NOTATION_NODE:
|
||||
if ((wts & NodeFilter.SHOW_NOTATION) == 0)
|
||||
{
|
||||
super.serialize(node, out);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (filter.acceptNode(node))
|
||||
{
|
||||
case NodeFilter.FILTER_ACCEPT:
|
||||
super.serialize(node, out);
|
||||
break;
|
||||
case NodeFilter.FILTER_REJECT:
|
||||
break;
|
||||
case NodeFilter.FILTER_SKIP:
|
||||
Node first = node.getFirstChild();
|
||||
if (first != null)
|
||||
{
|
||||
serialize(first, out);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- DOMConfiguration --
|
||||
|
||||
public void setParameter(String name, Object value)
|
||||
throws DOMException
|
||||
{
|
||||
if ("discard-default-content".equals(name))
|
||||
{
|
||||
discardDefaultContent = "true".equals(value.toString());
|
||||
}
|
||||
else if ("xml-declaration".equals(name))
|
||||
{
|
||||
xmlDeclaration = "false".equals(value.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_SUPPORTED_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getParameter(String name)
|
||||
throws DOMException
|
||||
{
|
||||
if ("discard-default-content".equals(name))
|
||||
{
|
||||
return discardDefaultContent ? "true" : "false";
|
||||
}
|
||||
else if ("xml-declaration".equals(name))
|
||||
{
|
||||
return xmlDeclaration ? "true" : "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DomEx(DomEx.NOT_SUPPORTED_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canSetParameter(String name, Object value)
|
||||
{
|
||||
return contains(name);
|
||||
}
|
||||
|
||||
public DOMStringList getParameterNames()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// -- DOMStringList --
|
||||
|
||||
public String item(int i)
|
||||
{
|
||||
return (String) SUPPORTED_PARAMETERS.get(i);
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
return SUPPORTED_PARAMETERS.size();
|
||||
}
|
||||
|
||||
public boolean contains(String str)
|
||||
{
|
||||
return SUPPORTED_PARAMETERS.contains(str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
/* FilteredSAXEventSink.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import org.w3c.dom.ls.LSParserFilter;
|
||||
import org.w3c.dom.traversal.NodeFilter;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* A SAX event sink that calls out to a parser filter in order to decide
|
||||
* whether to insert nodes into the tree.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class FilteredSAXEventSink
|
||||
extends SAXEventSink
|
||||
{
|
||||
|
||||
final LSParserFilter filter;
|
||||
final int whatToShow;
|
||||
|
||||
/**
|
||||
* Stack of elements to insert.
|
||||
*/
|
||||
LinkedList nodes;
|
||||
|
||||
/**
|
||||
* Corresponding stack of filter decisions about the nodes.
|
||||
*/
|
||||
LinkedList decisions;
|
||||
|
||||
/**
|
||||
* True when rejecting child nodes.
|
||||
*/
|
||||
boolean rejecting;
|
||||
|
||||
FilteredSAXEventSink(LSParserFilter filter)
|
||||
{
|
||||
this.filter = filter;
|
||||
whatToShow = filter.getWhatToShow();
|
||||
}
|
||||
|
||||
public void startDocument()
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
nodes = new LinkedList();
|
||||
decisions = new LinkedList();
|
||||
|
||||
super.startDocument();
|
||||
}
|
||||
|
||||
public void endDocument()
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
super.endDocument();
|
||||
|
||||
switch (getDecision(ctx, false))
|
||||
{
|
||||
case LSParserFilter.FILTER_REJECT:
|
||||
ctx = null;
|
||||
doc = null;
|
||||
break;
|
||||
}
|
||||
|
||||
nodes = null;
|
||||
decisions = null;
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes atts)
|
||||
throws SAXException
|
||||
{
|
||||
if (rejecting || interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Element element = createElement(uri, localName, qName, atts);
|
||||
ctx = element;
|
||||
|
||||
short decision = getDecision(element, true);
|
||||
nodes.addLast(element);
|
||||
decisions.addLast(new Short(decision));
|
||||
|
||||
switch (decision)
|
||||
{
|
||||
case LSParserFilter.FILTER_REJECT:
|
||||
rejecting = true;
|
||||
break;
|
||||
case LSParserFilter.FILTER_INTERRUPT:
|
||||
interrupted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected Attr createAttr(Attributes atts, int index)
|
||||
{
|
||||
Attr attr = super.createAttr(atts, index);
|
||||
short decision = getDecision(attr, false);
|
||||
switch (decision)
|
||||
{
|
||||
case LSParserFilter.FILTER_REJECT:
|
||||
return null;
|
||||
case LSParserFilter.FILTER_INTERRUPT:
|
||||
interrupted = true;
|
||||
return null;
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
if (rejecting || interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
super.endElement(uri, localName, qName);
|
||||
|
||||
Element element = (Element) nodes.removeLast();
|
||||
Node parent = nodes.isEmpty() ? doc : (Node) nodes.getLast();
|
||||
ctx = parent;
|
||||
short decision = ((Short) decisions.removeLast()).shortValue();
|
||||
switch (decision)
|
||||
{
|
||||
case LSParserFilter.FILTER_SKIP:
|
||||
// Add all children of element to parent
|
||||
for (Node child = element.getFirstChild(); child != null;
|
||||
child = child.getNextSibling())
|
||||
{
|
||||
parent.insertBefore(child, element);
|
||||
}
|
||||
return;
|
||||
case LSParserFilter.FILTER_REJECT:
|
||||
rejecting = false;
|
||||
break;
|
||||
}
|
||||
decision = getDecision(element, false);
|
||||
switch (decision)
|
||||
{
|
||||
case LSParserFilter.FILTER_ACCEPT:
|
||||
parent.appendChild(element);
|
||||
break;
|
||||
case LSParserFilter.FILTER_INTERRUPT:
|
||||
interrupted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void characters(char[] c, int off, int len)
|
||||
throws SAXException
|
||||
{
|
||||
if (rejecting || interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Text text = createText(c, off, len);
|
||||
short decision = getDecision(text, false);
|
||||
switch (decision)
|
||||
{
|
||||
case LSParserFilter.FILTER_ACCEPT:
|
||||
ctx.appendChild(text);
|
||||
break;
|
||||
case LSParserFilter.FILTER_INTERRUPT:
|
||||
interrupted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void processingInstruction(String target, String data)
|
||||
throws SAXException
|
||||
{
|
||||
if (rejecting || interrupted || inDTD)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Node pi = createProcessingInstruction(target, data);
|
||||
short decision = getDecision(pi, false);
|
||||
switch (decision)
|
||||
{
|
||||
case LSParserFilter.FILTER_ACCEPT:
|
||||
ctx.appendChild(pi);
|
||||
break;
|
||||
case LSParserFilter.FILTER_INTERRUPT:
|
||||
interrupted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void startDTD(String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Node doctype = createDocumentType(name, publicId, systemId);
|
||||
ctx = doctype;
|
||||
inDTD = true;
|
||||
nodes.addLast(doctype);
|
||||
decisions.addLast(new Short(LSParserFilter.FILTER_ACCEPT));
|
||||
}
|
||||
|
||||
public void endDTD()
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Node doctype = (Node) nodes.removeLast();
|
||||
decisions.removeLast();
|
||||
inDTD = false;
|
||||
ctx = doc;
|
||||
short decision = getDecision(doctype, false);
|
||||
switch (decision)
|
||||
{
|
||||
case LSParserFilter.FILTER_ACCEPT:
|
||||
ctx.appendChild(doctype);
|
||||
break;
|
||||
case LSParserFilter.FILTER_INTERRUPT:
|
||||
interrupted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void comment(char[] c, int off, int len)
|
||||
throws SAXException
|
||||
{
|
||||
if (rejecting || interrupted || inDTD)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Node comment = createComment(c, off, len);
|
||||
short decision = getDecision(comment, false);
|
||||
switch (decision)
|
||||
{
|
||||
case LSParserFilter.FILTER_ACCEPT:
|
||||
ctx.appendChild(comment);
|
||||
break;
|
||||
case LSParserFilter.FILTER_INTERRUPT:
|
||||
interrupted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO declarations
|
||||
|
||||
short getDecision(Node node, boolean start)
|
||||
{
|
||||
boolean show = (whatToShow == NodeFilter.SHOW_ALL);
|
||||
if (!show)
|
||||
{
|
||||
switch (node.getNodeType())
|
||||
{
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_ATTRIBUTE) != 0);
|
||||
break;
|
||||
case Node.TEXT_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_TEXT) != 0);
|
||||
break;
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_CDATA_SECTION) != 0);
|
||||
break;
|
||||
case Node.ELEMENT_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_ELEMENT) != 0);
|
||||
break;
|
||||
case Node.COMMENT_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_COMMENT) != 0);
|
||||
break;
|
||||
case Node.DOCUMENT_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_DOCUMENT) != 0);
|
||||
break;
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_PROCESSING_INSTRUCTION) != 0);
|
||||
break;
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_DOCUMENT_FRAGMENT) != 0);
|
||||
break;
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_DOCUMENT_TYPE) != 0);
|
||||
break;
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_ENTITY_REFERENCE) != 0);
|
||||
break;
|
||||
case Node.ENTITY_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_ENTITY) != 0);
|
||||
break;
|
||||
case Node.NOTATION_NODE:
|
||||
show = ((whatToShow & NodeFilter.SHOW_NOTATION) != 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!show)
|
||||
{
|
||||
return LSParserFilter.FILTER_ACCEPT;
|
||||
}
|
||||
if (start)
|
||||
{
|
||||
return filter.startElement((Element) node);
|
||||
}
|
||||
return filter.acceptNode(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/* ReaderInputStream.java --
|
||||
Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* Character stream wrapper.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
* @author <a href='mailto:mark@klomp.org'>Mark Wielaard</a>
|
||||
*/
|
||||
public class ReaderInputStream
|
||||
extends InputStream
|
||||
{
|
||||
|
||||
private Reader reader;
|
||||
private String encoding;
|
||||
|
||||
// Holds extra spillover data if necessary
|
||||
private byte extra[];
|
||||
private int pos;
|
||||
|
||||
private byte extra_marked[];
|
||||
private int pos_marked;
|
||||
|
||||
public ReaderInputStream(Reader reader)
|
||||
{
|
||||
this.reader = reader;
|
||||
this.encoding = "UTF-8";
|
||||
}
|
||||
|
||||
void setEncoding(String encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
if (extra != null)
|
||||
{
|
||||
int result = extra[pos];
|
||||
pos++;
|
||||
if (pos >= extra.length)
|
||||
{
|
||||
extra = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return reader.read();
|
||||
}
|
||||
|
||||
public int read(byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
if (len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (extra != null)
|
||||
{
|
||||
int available = extra.length - pos;
|
||||
int l = available < len ? available : len;
|
||||
System.arraycopy(extra, 0, b, off, l);
|
||||
pos += l;
|
||||
if (pos >= extra.length)
|
||||
{
|
||||
extra = null;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
char[] c = new char[len];
|
||||
int l = reader.read(c, 0, len);
|
||||
if (l == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
String s = new String(c, 0, l);
|
||||
byte[] d = s.getBytes(encoding);
|
||||
|
||||
int available = d.length;
|
||||
int more = d.length - len;
|
||||
if (more > 0)
|
||||
{
|
||||
extra = new byte[more];
|
||||
pos = 0;
|
||||
System.arraycopy(d, len, extra, 0, more);
|
||||
available -= more;
|
||||
}
|
||||
|
||||
System.arraycopy(d, 0, b, off, available);
|
||||
return available;
|
||||
}
|
||||
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
reader.close();
|
||||
}
|
||||
|
||||
public boolean markSupported()
|
||||
{
|
||||
return reader.markSupported();
|
||||
}
|
||||
|
||||
public void mark(int limit)
|
||||
{
|
||||
if (extra != null)
|
||||
{
|
||||
extra_marked = new byte[extra.length];
|
||||
System.arraycopy(extra, 0, extra_marked, 0, extra.length);
|
||||
pos_marked = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
extra_marked = null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Note that this might be a bit more than asked for.
|
||||
// Because we might also have the extra_marked bytes.
|
||||
// That is fine (and necessary for reset() to work).
|
||||
reader.mark(limit);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset()
|
||||
throws IOException
|
||||
{
|
||||
extra = extra_marked;
|
||||
pos = pos_marked;
|
||||
extra_marked = null;
|
||||
|
||||
reader.reset();
|
||||
}
|
||||
|
||||
public long skip(long n)
|
||||
throws IOException
|
||||
{
|
||||
long done = 0;
|
||||
if (extra != null)
|
||||
{
|
||||
int available = extra.length - pos;
|
||||
done = available < n ? available : n;
|
||||
pos += done;
|
||||
if (pos >= extra.length)
|
||||
{
|
||||
extra = null;
|
||||
}
|
||||
}
|
||||
|
||||
n -= done;
|
||||
if (n > 0)
|
||||
{
|
||||
return reader.skip(n) + done;
|
||||
}
|
||||
else
|
||||
{
|
||||
return done;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns conservative number of bytes available without blocking.
|
||||
* Actual number of bytes that can be read without blocking might
|
||||
* be (much) bigger.
|
||||
*/
|
||||
public int available()
|
||||
throws IOException
|
||||
{
|
||||
if (extra != null)
|
||||
{
|
||||
return pos - extra.length;
|
||||
}
|
||||
|
||||
return reader.ready() ? 1 : 0;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getClass().getName() + "[" + reader + ", " + encoding + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
/* SAXEventSink.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.xml.XMLConstants;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Entity;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.DTDHandler;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.Attributes2;
|
||||
import org.xml.sax.ext.DeclHandler;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
import gnu.xml.aelfred2.ContentHandler2;
|
||||
import gnu.xml.dom.DomAttr;
|
||||
import gnu.xml.dom.DomDocument;
|
||||
import gnu.xml.dom.DomDoctype;
|
||||
|
||||
/**
|
||||
* A SAX content and lexical handler used to construct a DOM document.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class SAXEventSink
|
||||
implements ContentHandler2, LexicalHandler, DTDHandler, DeclHandler
|
||||
{
|
||||
|
||||
private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
|
||||
private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
|
||||
|
||||
boolean namespaceAware;
|
||||
boolean ignoreWhitespace;
|
||||
boolean expandEntityReferences;
|
||||
boolean ignoreComments;
|
||||
boolean coalescing;
|
||||
|
||||
DomDocument doc; // document being constructed
|
||||
Node ctx; // current context (parent node)
|
||||
LinkedList entityCtx; // entity context
|
||||
List pending; // namespace nodes waiting for a declaring element
|
||||
Locator locator;
|
||||
boolean inCDATA;
|
||||
boolean inDTD;
|
||||
boolean interrupted;
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
interrupted = true;
|
||||
}
|
||||
|
||||
// -- ContentHandler2 --
|
||||
|
||||
public void setDocumentLocator(Locator locator)
|
||||
{
|
||||
this.locator = locator;
|
||||
}
|
||||
|
||||
public void startDocument()
|
||||
throws SAXException
|
||||
{
|
||||
if (namespaceAware)
|
||||
{
|
||||
pending = new LinkedList();
|
||||
}
|
||||
doc = new DomDocument();
|
||||
doc.setStrictErrorChecking(false);
|
||||
doc.setBuilding(true);
|
||||
ctx = doc;
|
||||
}
|
||||
|
||||
public void xmlDecl(String version, String encoding, boolean standalone,
|
||||
String inputEncoding)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
doc.setXmlVersion(version);
|
||||
doc.setXmlEncoding(encoding);
|
||||
doc.setXmlStandalone(standalone);
|
||||
doc.setInputEncoding(inputEncoding);
|
||||
}
|
||||
|
||||
public void endDocument()
|
||||
throws SAXException
|
||||
{
|
||||
doc.setStrictErrorChecking(true);
|
||||
doc.setBuilding(false);
|
||||
DomDoctype doctype = (DomDoctype) doc.getDoctype();
|
||||
if (doctype != null)
|
||||
{
|
||||
doctype.makeReadonly();
|
||||
}
|
||||
ctx = null;
|
||||
locator = null;
|
||||
}
|
||||
|
||||
public void startPrefixMapping(String prefix, String uri)
|
||||
throws SAXException
|
||||
{
|
||||
if (namespaceAware)
|
||||
{
|
||||
String nsName = (prefix != null && prefix.length() > 0) ?
|
||||
XMLNS_PREFIX + ":" + prefix : XMLNS_PREFIX;
|
||||
DomAttr ns = (DomAttr) doc.createAttributeNS(XMLNS_URI, nsName);
|
||||
ns.setNodeValue(uri);
|
||||
if (ctx.getNodeType() == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
// Add to owner element
|
||||
Node target = ((Attr) ctx).getOwnerElement();
|
||||
target.getAttributes().setNamedItemNS(ns);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add to pending list; namespace node will be inserted when
|
||||
// element is seen
|
||||
pending.add(ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void endPrefixMapping(String prefix)
|
||||
throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes atts)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Element element = createElement(uri, localName, qName, atts);
|
||||
// add element to context
|
||||
ctx.appendChild(element);
|
||||
ctx = element;
|
||||
}
|
||||
|
||||
protected Element createElement(String uri, String localName, String qName,
|
||||
Attributes atts)
|
||||
throws SAXException
|
||||
{
|
||||
// create element node
|
||||
Element element = namespaceAware ?
|
||||
doc.createElementNS(uri, qName) :
|
||||
doc.createElement(qName);
|
||||
NamedNodeMap attrs = element.getAttributes();
|
||||
if (namespaceAware && !pending.isEmpty())
|
||||
{
|
||||
// add pending namespace nodes
|
||||
for (Iterator i = pending.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node ns = (Node) i.next();
|
||||
attrs.setNamedItemNS(ns);
|
||||
}
|
||||
pending.clear();
|
||||
}
|
||||
// add attributes
|
||||
int len = atts.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
// create attribute
|
||||
Attr attr = createAttr(atts, i);
|
||||
if (attr != null)
|
||||
{
|
||||
// add attribute to element
|
||||
if (namespaceAware)
|
||||
{
|
||||
attrs.setNamedItemNS(attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
attrs.setNamedItem(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
protected Attr createAttr(Attributes atts, int index)
|
||||
{
|
||||
DomAttr attr;
|
||||
if (namespaceAware)
|
||||
{
|
||||
String a_uri = atts.getURI(index);
|
||||
String a_qName = atts.getQName(index);
|
||||
attr = (DomAttr) doc.createAttributeNS(a_uri, a_qName);
|
||||
}
|
||||
else
|
||||
{
|
||||
String a_qName = atts.getQName(index);
|
||||
attr = (DomAttr) doc.createAttribute(a_qName);
|
||||
}
|
||||
attr.setNodeValue(atts.getValue(index));
|
||||
if (atts instanceof Attributes2)
|
||||
{
|
||||
Attributes2 atts2 = (Attributes2) atts;
|
||||
// TODO attr.setDeclared(atts2.isDeclared(index));
|
||||
attr.setSpecified(atts2.isSpecified(index));
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (namespaceAware)
|
||||
{
|
||||
pending.clear();
|
||||
}
|
||||
ctx = ctx.getParentNode();
|
||||
}
|
||||
|
||||
public void characters(char[] c, int off, int len)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ctx.appendChild(createText(c, off, len));
|
||||
}
|
||||
|
||||
protected Text createText(char[] c, int off, int len)
|
||||
throws SAXException
|
||||
{
|
||||
Text text = (inCDATA && !coalescing) ?
|
||||
doc.createCDATASection(new String(c, off, len)) :
|
||||
doc.createTextNode(new String(c, off, len));
|
||||
return text;
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(char[] c, int off, int len)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!ignoreWhitespace)
|
||||
{
|
||||
characters(c, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
public void processingInstruction(String target, String data)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!inDTD)
|
||||
{
|
||||
Node pi = createProcessingInstruction(target, data);
|
||||
ctx.appendChild(pi);
|
||||
}
|
||||
}
|
||||
|
||||
protected Node createProcessingInstruction(String target, String data)
|
||||
{
|
||||
return doc.createProcessingInstruction(target, data);
|
||||
}
|
||||
|
||||
public void skippedEntity(String name)
|
||||
throws SAXException
|
||||
{
|
||||
// This callback is totally pointless
|
||||
}
|
||||
|
||||
// -- LexicalHandler --
|
||||
|
||||
public void startDTD(String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Node doctype = createDocumentType(name, publicId, systemId);
|
||||
doc.appendChild(doctype);
|
||||
ctx = doctype;
|
||||
inDTD = true;
|
||||
}
|
||||
|
||||
protected Node createDocumentType(String name, String publicId,
|
||||
String systemId)
|
||||
{
|
||||
return new DomDoctype(doc, name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void endDTD()
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
inDTD = false;
|
||||
ctx = ctx.getParentNode();
|
||||
}
|
||||
|
||||
public void startEntity(String name)
|
||||
throws SAXException
|
||||
{
|
||||
DocumentType doctype = doc.getDoctype();
|
||||
if (doctype == null)
|
||||
{
|
||||
throw new SAXException("SAX parser error: " +
|
||||
"reference to entity in undeclared doctype");
|
||||
}
|
||||
if ("[dtd]".equals(name) || name.charAt(0) == '%')
|
||||
{
|
||||
// Ignore DTD and parameter entities
|
||||
ctx = doctype;
|
||||
return;
|
||||
}
|
||||
// Get entity
|
||||
NamedNodeMap entities = doctype.getEntities();
|
||||
Entity entity = (Entity) entities.getNamedItem(name);
|
||||
if (entity == null)
|
||||
{
|
||||
throw new SAXException("SAX parser error: " +
|
||||
"reference to undeclared entity: " + name);
|
||||
}
|
||||
pushEntity(entity);
|
||||
}
|
||||
|
||||
public void endEntity(String name)
|
||||
throws SAXException
|
||||
{
|
||||
if ("[dtd]".equals(name) || name.charAt(0) == '%')
|
||||
{
|
||||
// Ignore DTD and parameter entities
|
||||
return;
|
||||
}
|
||||
Entity entity = popEntity();
|
||||
// TODO resolve external entities to ensure that entity has content
|
||||
if (expandEntityReferences)
|
||||
{
|
||||
// Get entity content
|
||||
for (Node child = entity.getFirstChild(); child != null;
|
||||
child = child.getNextSibling())
|
||||
{
|
||||
ctx.appendChild(child);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Node entityReference = doc.createEntityReference(name);
|
||||
ctx.appendChild(entityReference);
|
||||
}
|
||||
}
|
||||
|
||||
void pushEntity(Node entity)
|
||||
{
|
||||
if (entityCtx == null)
|
||||
{
|
||||
entityCtx = new LinkedList();
|
||||
}
|
||||
entityCtx.addLast(ctx);
|
||||
ctx = entity;
|
||||
}
|
||||
|
||||
Entity popEntity()
|
||||
{
|
||||
Entity ret = (Entity) ctx;
|
||||
ctx = (Node) entityCtx.removeLast();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void startCDATA()
|
||||
throws SAXException
|
||||
{
|
||||
inCDATA = true;
|
||||
}
|
||||
|
||||
public void endCDATA()
|
||||
throws SAXException
|
||||
{
|
||||
inCDATA = false;
|
||||
}
|
||||
|
||||
public void comment(char[] c, int off, int len)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!inDTD)
|
||||
{
|
||||
Node comment = createComment(c, off, len);
|
||||
ctx.appendChild(comment);
|
||||
}
|
||||
}
|
||||
|
||||
protected Node createComment(char[] c, int off, int len)
|
||||
{
|
||||
return doc.createComment(new String(c, off, len));
|
||||
}
|
||||
|
||||
// -- DTDHandler --
|
||||
|
||||
public void notationDecl(String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DomDoctype doctype = (DomDoctype) ctx;
|
||||
doctype.declareNotation(name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void unparsedEntityDecl(String name, String publicId, String systemId,
|
||||
String notationName)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DomDoctype doctype = (DomDoctype) ctx;
|
||||
Entity entity = doctype.declareEntity(name, publicId, systemId,
|
||||
notationName);
|
||||
}
|
||||
|
||||
// -- DeclHandler --
|
||||
|
||||
public void elementDecl(String name, String model)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DomDoctype doctype = (DomDoctype) ctx;
|
||||
doctype.elementDecl(name, model);
|
||||
}
|
||||
|
||||
public void attributeDecl(String eName, String aName, String type,
|
||||
String mode, String value)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DomDoctype doctype = (DomDoctype) ctx;
|
||||
doctype.attributeDecl(eName, aName, type, mode, value);
|
||||
}
|
||||
|
||||
public void internalEntityDecl(String name, String value)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DomDoctype doctype = (DomDoctype) ctx;
|
||||
Entity entity = doctype.declareEntity(name, null, null, null);
|
||||
if (entity != null)
|
||||
{
|
||||
Node text = doc.createTextNode(value);
|
||||
entity.appendChild(text);
|
||||
}
|
||||
}
|
||||
|
||||
public void externalEntityDecl(String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DomDoctype doctype = (DomDoctype) ctx;
|
||||
Entity entity = doctype.declareEntity(name, publicId, systemId, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/* WriterOutputStream.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.dom.ls;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Character stream wrapper.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class WriterOutputStream
|
||||
extends OutputStream
|
||||
{
|
||||
|
||||
private Writer writer;
|
||||
private String encoding;
|
||||
|
||||
public WriterOutputStream(Writer writer)
|
||||
{
|
||||
this.writer = writer;
|
||||
this.encoding = "UTF-8";
|
||||
}
|
||||
|
||||
void setEncoding(String encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public void write(int c)
|
||||
throws IOException
|
||||
{
|
||||
writer.write(c);
|
||||
}
|
||||
|
||||
public void write(byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
write(b, 0, b.length);
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
writer.write(new String(b, off, len, encoding));
|
||||
}
|
||||
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
writer.close();
|
||||
}
|
||||
|
||||
public void flush()
|
||||
throws IOException
|
||||
{
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<p>
|
||||
This is a Free Software DOM Level 3 implementation, supporting these features:
|
||||
<ul>
|
||||
<li>"XML"</li>
|
||||
<li>"Events"</li>
|
||||
<li>"MutationEvents"</li>
|
||||
<li>"HTMLEvents" (won't generate them though)</li>
|
||||
<li>"UIEvents" (also won't generate them)</li>
|
||||
<li>"USER-Events" (a conformant extension)</li>
|
||||
<li>"Traversal" (optional)</li>
|
||||
<li>"XPath"</li>
|
||||
<li>"LS" and "LS-Async"</li>
|
||||
</ul>
|
||||
It is intended to be a reasonable base both for
|
||||
experimentation and supporting additional DOM modules as clean layers.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that while DOM does not specify its behavior in the
|
||||
face of concurrent access, this implementation does.
|
||||
Specifically:
|
||||
<ul>
|
||||
<li>If only one thread at a time accesses a Document,
|
||||
of if several threads cooperate for read-only access,
|
||||
then no concurrency conflicts will occur.</li>
|
||||
<li>If several threads mutate a given document
|
||||
(or send events using it) at the same time,
|
||||
there is currently no guarantee that
|
||||
they won't interfere with each other.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h3>Design Goals</h3>
|
||||
|
||||
<p>
|
||||
A number of DOM implementations are available in Java, including
|
||||
commercial ones from Sun, IBM, Oracle, and DataChannel as well as
|
||||
noncommercial ones from Docuverse, OpenXML, and Silfide. Why have
|
||||
another? Some of the goals of this version:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Advanced DOM support. This was the first generally available
|
||||
implementation of DOM Level 2 in Java, and one of the first Level 3
|
||||
and XPath implementations.</li>
|
||||
|
||||
<li> Free Software. This one is distributed under the GPL (with
|
||||
"library exception") so it can be used with a different class of
|
||||
application.</li>
|
||||
|
||||
<li>Second implementation syndrome. I can do it simpler this time
|
||||
around ... and heck, writing it only takes a bit over a day once you
|
||||
know your way around.</li>
|
||||
|
||||
<li>Sanity check the then-current Last Call DOM draft. Best to find
|
||||
bugs early, when they're relatively fixable. Yes, bugs were found.</li>
|
||||
|
||||
<li>Modularity. Most of the implementations mentioned above are part
|
||||
of huge packages; take all (including bugs, of which some have far
|
||||
too many), or take nothing. I prefer a menu approach, when possible.
|
||||
This code is standalone, not beholden to any particular parser or XSL
|
||||
or XPath code.</li>
|
||||
|
||||
<li>OK, I'm a hacker, I like to write code.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
This also works with the GNU Compiler for Java (GCJ). GCJ promises
|
||||
to be quite the environment for programming Java, both directly and from
|
||||
C++ using the new CNI interfaces (which really use C++, unlike JNI). </p>
|
||||
|
||||
|
||||
<h3>Open Issues</h3>
|
||||
|
||||
<p>At this writing:</p>
|
||||
<ul>
|
||||
<li>See below for some restrictions on the mutation event
|
||||
support ... some events aren't reported (and likely won't be).</li>
|
||||
|
||||
<li>More testing and conformance work is needed.</li>
|
||||
|
||||
<li>We need an XML Schema validator (actually we need validation in the DOM
|
||||
full stop).</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
I ran a profiler a few times and remove some of the performance hotspots,
|
||||
but it's not tuned. Reporting mutation events, in particular, is
|
||||
rather costly -- it started at about a 40% penalty for appendNode calls,
|
||||
I've got it down around 12%, but it'll be hard to shrink it much further.
|
||||
The overall code size is relatively small, though you may want to be rid of
|
||||
many of the unused DOM interface classes (HTML, CSS, and so on).
|
||||
</p>
|
||||
|
||||
|
||||
<h2><a name="features">Features of this Package</a></h2>
|
||||
|
||||
<p> Starting with DOM Level 2, you can really see that DOM is constructed
|
||||
as a bunch of optional modules around a core of either XML or HTML
|
||||
functionality. Different implementations will support different optional
|
||||
modules. This implementation provides a set of features that should be
|
||||
useful if you're not depending on the HTML functionality (lots of convenience
|
||||
functions that mostly don't buy much except API surface area) and user
|
||||
interface support. That is, browsers will want more -- but what they
|
||||
need should be cleanly layered over what's already here. </p>
|
||||
|
||||
<h3> Core Feature Set: "XML" </h3>
|
||||
|
||||
<p> This DOM implementation supports the "XML" feature set, which basically
|
||||
gets you four things over the bare core (which you're officially not supposed
|
||||
to implement except in conjunction with the "XML" or "HTML" feature). In
|
||||
order of decreasing utility, those four things are: </p> <ol>
|
||||
|
||||
<li> ProcessingInstruction nodes. These are probably the most
|
||||
valuable thing. Handy little buggers, in part because all the APIs
|
||||
you need to use them are provided, and they're designed to let you
|
||||
escape XML document structure rules in controlled ways.</li>
|
||||
|
||||
<li> CDATASection nodes. These are of of limited utility since CDATA
|
||||
is just text that prints funny. These are of use to some sorts of
|
||||
applications, though I encourage folk to not use them. </li>
|
||||
|
||||
<li> DocumentType nodes, and associated Notation and Entity nodes.
|
||||
These appear to be useless. Briefly, these "Type" nodes expose no
|
||||
typing information. They're only really usable to expose some lexical
|
||||
structure that almost every application needs to ignore. (XML editors
|
||||
might like to see them, but they need true typing information much more.)
|
||||
I strongly encourage people not to use these. </li>
|
||||
|
||||
<li> EntityReference nodes can show up. These are actively annoying,
|
||||
since they add an extra level of hierarchy, are the cause of most of
|
||||
the complexity in attribute values, and their contents are immutable.
|
||||
Avoid these.</li>
|
||||
|
||||
</ol>
|
||||
|
||||
<h3> Optional Feature Sets: "Events", and friends </h3>
|
||||
|
||||
<p> Events may be one of the more interesting new features in Level 2.
|
||||
This package provides the core feature set and exposes mutation events.
|
||||
No gooey events though; if you want that, write a layered implementation! </p>
|
||||
|
||||
<p> Three mutation events aren't currently generated:</p> <ul>
|
||||
|
||||
<li> <em>DOMSubtreeModified</em> is poorly specified. Think of this
|
||||
as generating one such event around the time of finalization, which
|
||||
is a fully conformant implementation. This implementation is exactly
|
||||
as useful as that one. </li>
|
||||
|
||||
<li> <em>DOMNodeRemovedFromDocument</em> and
|
||||
<em>DOMNodeInsertedIntoDocument</em> are supposed to get sent to
|
||||
every node in a subtree that gets removed or inserted (respectively).
|
||||
This can be <em>extremely costly</em>, and the removal and insertion
|
||||
processing is already significantly slower due to event reporting.
|
||||
It's much easier, and more efficient, to have a listener higher in the
|
||||
tree watch removal and insertion events through the bubbling or capture
|
||||
mechanisms, than it is to watch for these two events.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> In addition, certain kinds of attribute modification aren't reported.
|
||||
A fix is known, but it couldn't report the previous value of the attribute.
|
||||
More work could fix all of this (as well as reduce the generally high cost
|
||||
of childful attributes), but that's not been done yet. </p>
|
||||
|
||||
<p> Also, note that it is a <em>Bad Thing™</em> to have the listener
|
||||
for a mutation event change the ancestry for the target of that event.
|
||||
Or to prevent mutation events from bubbling to where they're needed.
|
||||
Just don't do those, OK? </p>
|
||||
|
||||
<p> As an experimental feature (named "USER-Events"), you can provide
|
||||
your own "user" events. Just name them anything starting with "USER-"
|
||||
and you're set. Dispatch them through, bubbling, capturing, or what
|
||||
ever takes your fancy. One important thing you can't currently do is
|
||||
pass any data (like an object) with those events. Maybe later there
|
||||
will be a "UserEvent" interface letting you get some substantial use
|
||||
out of this mechanism even if you're not "inside" of a DOM package.</p>
|
||||
|
||||
<p> You can create and send HTML events. Ditto UIEvents. Since DOM
|
||||
doesn't require a UI, it's the UI's job to send them; perhaps that's
|
||||
part of your application. </p>
|
||||
|
||||
<p><em>This package may be built without the ability to report mutation
|
||||
events, gaining a significant speedup in DOM construction time. However,
|
||||
if that is done then certain other features -- notably node iterators
|
||||
and getElementsByTagname -- will not be available.</em>
|
||||
|
||||
|
||||
<h3> Optional Feature: "Traversal" </h3>
|
||||
|
||||
<p> Each DOM node has all you need to walk to everything connected
|
||||
to that node. Lightweight, efficient utilities are easily layered on
|
||||
top of just the core APIs. </p>
|
||||
|
||||
<p> Traversal APIs are an optional part of DOM Level 2, providing
|
||||
a not-so-lightweight way to walk over DOM trees, if your application
|
||||
didn't already have such utilities for use with data represented via
|
||||
DOM. Implementing this helped debug the (optional) event and mutation
|
||||
event subsystems, so it's provided here. </p>
|
||||
|
||||
<p> At this writing, the "TreeWalker" interface isn't implemented. </p>
|
||||
|
||||
|
||||
|
||||
<h2><a name='avoid'>DOM Functionality to Avoid</a></h2>
|
||||
|
||||
<p> For what appear to be a combination of historical and "committee
|
||||
logic" reasons, DOM has a number of <em>features which I strongly advise
|
||||
you to avoid using</em> in your library and application code. These
|
||||
include the following types of DOM nodes; see the documentation for the
|
||||
implementation class for more information: <ul>
|
||||
|
||||
<li> CDATASection
|
||||
(<a href='DomCDATA.html'>DomCDATA</a> class)
|
||||
... use normal Text nodes instead, so you don't have to make
|
||||
every algorithm recognize multiple types of character data
|
||||
|
||||
<li> DocumentType
|
||||
(<a href='DomDoctype.html'>DomDocType</a> class)
|
||||
... if this held actual typing information, it might be useful
|
||||
|
||||
<li> Entity
|
||||
(<a href='DomEntity.html'>DomEntity</a> class)
|
||||
... neither parsed nor unparsed entities work well in DOM; it
|
||||
won't even tell you which attributes identify unparsed entities
|
||||
|
||||
<li> EntityReference
|
||||
(<a href='DomEntityReference.html'>DomEntityReference</a> class)
|
||||
... permitted implementation variances are extreme, all children
|
||||
are readonly, and these can interact poorly with namespaces
|
||||
|
||||
<li> Notation
|
||||
(<a href='DomNotation.html'>DomNotation</a> class)
|
||||
... only really usable with unparsed entities (which aren't well
|
||||
supported; see above) or perhaps with PIs after the DTD, not with
|
||||
NOTATION attributes
|
||||
|
||||
</ul>
|
||||
|
||||
<p> If you really need to use unparsed entities or notations, use SAX;
|
||||
it offers better support for all DTD-related functionality.
|
||||
It also exposes actual
|
||||
document typing information (such as element content models).</p>
|
||||
|
||||
<p> Also, when accessing attribute values, use methods that provide their
|
||||
values as single strings, rather than those which expose value substructure
|
||||
(Text and EntityReference nodes). (See the <a href='DomAttr.html'>DomAttr</a>
|
||||
documentation for more information.) </p>
|
||||
|
||||
<p> Note that many of these features were provided as partial support for
|
||||
editor functionality (including the incomplete DTD access). Full editor
|
||||
functionality requires access to potentially malformed lexical structure,
|
||||
at the level of unparsed tokens and below. Access at such levels is so
|
||||
complex that using it in non-editor applications sacrifices all the
|
||||
benefits of XML; editor aplications need extremely specialized APIs. </p>
|
||||
|
||||
<p> (This isn't a slam against DTDs, note; only against the broken support
|
||||
for them in DOM. Even despite inclusion of some dubious SGML legacy features
|
||||
such as notations and unparsed entities,
|
||||
and the ongoing proliferation of alternative schema and validation tools,
|
||||
DTDs are still the most widely adopted tool
|
||||
to constrain XML document structure.
|
||||
Alternative schemes generally focus on data transfer style
|
||||
applications; open document architectures comparable to
|
||||
DocBook 4.0 don't yet exist in the schema world.
|
||||
Feel free to use DTDs; just don't expect DOM to help you.) </p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/* CallFilter.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.ext.*;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import gnu.xml.util.Resolver;
|
||||
import gnu.xml.util.XMLWriter;
|
||||
|
||||
|
||||
/**
|
||||
* Input is sent as an XML request to given URI, and the output of this
|
||||
* filter is the parsed response to that request.
|
||||
* A connection is opened to the remote URI when the startDocument call is
|
||||
* issued through this filter, and the request is finished when the
|
||||
* endDocument call is issued. Events should be written quickly enough to
|
||||
* prevent the remote HTTP server from aborting the connection due to
|
||||
* inactivity; you may want to buffer text in an earlier pipeline stage.
|
||||
* If your application requires validity checking of such
|
||||
* outputs, have the output pipeline include a validation stage.
|
||||
*
|
||||
* <p>In effect, this makes a remote procedure call to the URI, with the
|
||||
* request and response document syntax as chosen by the application.
|
||||
* <em>Note that all the input events must be seen, and sent to the URI,
|
||||
* before the first output event can be seen. </em> Clients are delayed
|
||||
* at least by waiting for the server to respond, constraining concurrency.
|
||||
* Services can thus be used to synchronize concurrent activities, and
|
||||
* even to prioritize service among different clients.
|
||||
*
|
||||
* <p> You are advised to avoid restricting yourself to an "RPC" model
|
||||
* for distributed computation. With a World Wide Web, network latencies
|
||||
* and failures (e.g. non-availability)
|
||||
* are significant; adopting a "procedure" model, rather than a workflow
|
||||
* model where bulk requests are sent and worked on asynchronously, is not
|
||||
* generally an optimal system-wide architecture. When the messages may
|
||||
* need authentication, such as with an OpenPGP signature, or when server
|
||||
* loads don't argue in favor of immediate responses, non-RPC models can
|
||||
* be advantageous. (So-called "peer to peer" computing models are one
|
||||
* additional type of model, though too often that term is applied to
|
||||
* systems that still have a centralized control structure.)
|
||||
*
|
||||
* <p> <em>Be strict in what you send, liberal in what you accept,</em> as
|
||||
* the Internet tradition goes. Strictly conformant data should never cause
|
||||
* problems to its receiver; make your request pipeline be very strict, and
|
||||
* don't compromise on that. Make your response pipeline strict as well,
|
||||
* but be ready to tolerate specific mild, temporary, and well-documented
|
||||
* variations from specific communications peers.
|
||||
*
|
||||
* @see XmlServlet
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
final public class CallFilter implements EventConsumer
|
||||
{
|
||||
private Requestor req;
|
||||
private EventConsumer next;
|
||||
private URL target;
|
||||
private URLConnection conn;
|
||||
private ErrorHandler errHandler;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes a call filter so that its inputs are sent to the
|
||||
* specified URI, and its outputs are sent to the next consumer
|
||||
* provided.
|
||||
*
|
||||
* @exception IOException if the URI isn't accepted as a URL
|
||||
*/
|
||||
// constructor used by PipelineFactory
|
||||
public CallFilter (String uri, EventConsumer next)
|
||||
throws IOException
|
||||
{
|
||||
this.next = next;
|
||||
req = new Requestor ();
|
||||
setCallTarget (uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the URI of the call target to be used.
|
||||
* Does not affect calls currently being made.
|
||||
*/
|
||||
final public void setCallTarget (String uri)
|
||||
throws IOException
|
||||
{
|
||||
target = new URL (uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the error handler to be used to present most fatal
|
||||
* errors.
|
||||
*/
|
||||
public void setErrorHandler (ErrorHandler handler)
|
||||
{
|
||||
req.setErrorHandler (handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the call target's URI.
|
||||
*/
|
||||
final public String getCallTarget ()
|
||||
{
|
||||
return target.toString ();
|
||||
}
|
||||
|
||||
/** Returns the content handler currently in use. */
|
||||
final public org.xml.sax.ContentHandler getContentHandler ()
|
||||
{
|
||||
return req;
|
||||
}
|
||||
|
||||
/** Returns the DTD handler currently in use. */
|
||||
final public DTDHandler getDTDHandler ()
|
||||
{
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the declaration or lexical handler currently in
|
||||
* use, or throws an exception for other properties.
|
||||
*/
|
||||
final public Object getProperty (String id)
|
||||
throws SAXNotRecognizedException
|
||||
{
|
||||
if (EventFilter.DECL_HANDLER.equals (id))
|
||||
return req;
|
||||
if (EventFilter.LEXICAL_HANDLER.equals (id))
|
||||
return req;
|
||||
throw new SAXNotRecognizedException (id);
|
||||
}
|
||||
|
||||
|
||||
// JDK 1.1 seems to need it to be done this way, sigh
|
||||
ErrorHandler getErrorHandler () { return errHandler; }
|
||||
|
||||
//
|
||||
// Takes input and echoes to server as POST input.
|
||||
// Then sends the POST reply to the next pipeline element.
|
||||
//
|
||||
final class Requestor extends XMLWriter
|
||||
{
|
||||
Requestor ()
|
||||
{
|
||||
super ((Writer)null);
|
||||
}
|
||||
|
||||
public synchronized void startDocument () throws SAXException
|
||||
{
|
||||
// Connect to remote object and set up to send it XML text
|
||||
try {
|
||||
if (conn != null)
|
||||
throw new IllegalStateException ("call is being made");
|
||||
|
||||
conn = target.openConnection ();
|
||||
conn.setDoOutput (true);
|
||||
conn.setRequestProperty ("Content-Type",
|
||||
"application/xml;charset=UTF-8");
|
||||
|
||||
setWriter (new OutputStreamWriter (
|
||||
conn.getOutputStream (),
|
||||
"UTF8"), "UTF-8");
|
||||
|
||||
} catch (IOException e) {
|
||||
fatal ("can't write (POST) to URI: " + target, e);
|
||||
}
|
||||
|
||||
// NOW base class can safely write that text!
|
||||
super.startDocument ();
|
||||
}
|
||||
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
//
|
||||
// Finish writing the request (for HTTP, a POST);
|
||||
// this closes the output stream.
|
||||
//
|
||||
super.endDocument ();
|
||||
|
||||
//
|
||||
// Receive the response.
|
||||
// Produce events for the next stage.
|
||||
//
|
||||
InputSource source;
|
||||
XMLReader producer;
|
||||
String encoding;
|
||||
|
||||
try {
|
||||
|
||||
source = new InputSource (conn.getInputStream ());
|
||||
|
||||
// FIXME if status is anything but success, report it!! It'd be good to
|
||||
// save the request data just in case we need to deal with a forward.
|
||||
|
||||
encoding = Resolver.getEncoding (conn.getContentType ());
|
||||
if (encoding != null)
|
||||
source.setEncoding (encoding);
|
||||
|
||||
producer = XMLReaderFactory.createXMLReader ();
|
||||
producer.setErrorHandler (getErrorHandler ());
|
||||
EventFilter.bind (producer, next);
|
||||
producer.parse (source);
|
||||
conn = null;
|
||||
|
||||
} catch (IOException e) {
|
||||
fatal ("I/O Exception reading response, " + e.getMessage (), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,969 @@
|
||||
/* DomConsumer.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.ext.DeclHandler;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
|
||||
import gnu.xml.aelfred2.ContentHandler2;
|
||||
import gnu.xml.util.DomParser;
|
||||
|
||||
|
||||
/**
|
||||
* This consumer builds a DOM Document from its input, acting either as a
|
||||
* pipeline terminus or as an intermediate buffer. When a document's worth
|
||||
* of events has been delivered to this consumer, that document is read with
|
||||
* a {@link DomParser} and sent to the next consumer. It is also available
|
||||
* as a read-once property.
|
||||
*
|
||||
* <p>The DOM tree is constructed as faithfully as possible. There are some
|
||||
* complications since a DOM should expose behaviors that can't be implemented
|
||||
* without API backdoors into that DOM, and because some SAX parsers don't
|
||||
* report all the information that DOM permits to be exposed. The general
|
||||
* problem areas involve information from the Document Type Declaration (DTD).
|
||||
* DOM only represents a limited subset, but has some behaviors that depend
|
||||
* on much deeper knowledge of a document's DTD. You shouldn't have much to
|
||||
* worry about unless you change handling of "noise" nodes from its default
|
||||
* setting (which ignores them all); note if you use JAXP to populate your
|
||||
* DOM trees, it wants to save "noise" nodes by default. (Such nodes include
|
||||
* ignorable whitespace, comments, entity references and CDATA boundaries.)
|
||||
* Otherwise, your
|
||||
* main worry will be if you use a SAX parser that doesn't flag ignorable
|
||||
* whitespace unless it's validating (few don't).
|
||||
*
|
||||
* <p> The SAX2 events used as input must contain XML Names for elements
|
||||
* and attributes, with original prefixes. In SAX2,
|
||||
* this is optional unless the "namespace-prefixes" parser feature is set.
|
||||
* Moreover, many application components won't provide completely correct
|
||||
* structures anyway. <em>Before you convert a DOM to an output document,
|
||||
* you should plan to postprocess it to create or repair such namespace
|
||||
* information.</em> The {@link NSFilter} pipeline stage does such work.
|
||||
*
|
||||
* <p> <em>Note: changes late in DOM L2 process made it impractical to
|
||||
* attempt to create the DocumentType node in any implementation-neutral way,
|
||||
* much less to populate it (L1 didn't support even creating such nodes).
|
||||
* To create and populate such a node, subclass the inner
|
||||
* {@link DomConsumer.Handler} class and teach it about the backdoors into
|
||||
* whatever DOM implementation you want. It's possible that some revised
|
||||
* DOM API (L3?) will make this problem solvable again. </em>
|
||||
*
|
||||
* @see DomParser
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class DomConsumer implements EventConsumer
|
||||
{
|
||||
private Class domImpl;
|
||||
|
||||
private boolean hidingCDATA = true;
|
||||
private boolean hidingComments = true;
|
||||
private boolean hidingWhitespace = true;
|
||||
private boolean hidingReferences = true;
|
||||
|
||||
private Handler handler;
|
||||
private ErrorHandler errHandler;
|
||||
|
||||
private EventConsumer next;
|
||||
|
||||
// FIXME: this can't be a generic pipeline stage just now,
|
||||
// since its input became a Class not a String (to be turned
|
||||
// into a class, using the right class loader)
|
||||
|
||||
|
||||
/**
|
||||
* Configures this pipeline terminus to use the specified implementation
|
||||
* of DOM when constructing its result value.
|
||||
*
|
||||
* @param impl class implementing {@link org.w3c.dom.Document Document}
|
||||
* which publicly exposes a default constructor
|
||||
*
|
||||
* @exception SAXException when there is a problem creating an
|
||||
* empty DOM document using the specified implementation
|
||||
*/
|
||||
public DomConsumer (Class impl)
|
||||
throws SAXException
|
||||
{
|
||||
domImpl = impl;
|
||||
handler = new Handler (this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the hook through which a subclass provides a handler
|
||||
* which knows how to access DOM extensions, specific to some
|
||||
* implementation, to record additional data in a DOM.
|
||||
* Treat this as part of construction; don't call it except
|
||||
* before (or between) parses.
|
||||
*/
|
||||
protected void setHandler (Handler h)
|
||||
{
|
||||
handler = h;
|
||||
}
|
||||
|
||||
|
||||
private Document emptyDocument ()
|
||||
throws SAXException
|
||||
{
|
||||
try {
|
||||
return (Document) domImpl.newInstance ();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SAXException ("can't access constructor: "
|
||||
+ e.getMessage ());
|
||||
} catch (InstantiationException e) {
|
||||
throw new SAXException ("can't instantiate Document: "
|
||||
+ e.getMessage ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configures this consumer as a buffer/filter, using the specified
|
||||
* DOM implementation when constructing its result value.
|
||||
*
|
||||
* <p> This event consumer acts as a buffer and filter, in that it
|
||||
* builds a DOM tree and then writes it out when <em>endDocument</em>
|
||||
* is invoked. Because of the limitations of DOM, much information
|
||||
* will as a rule not be seen in that replay. To get a full fidelity
|
||||
* copy of the input event stream, use a {@link TeeConsumer}.
|
||||
*
|
||||
* @param impl class implementing {@link org.w3c.dom.Document Document}
|
||||
* which publicly exposes a default constructor
|
||||
* @param next receives a "replayed" sequence of parse events when
|
||||
* the <em>endDocument</em> method is invoked.
|
||||
*
|
||||
* @exception SAXException when there is a problem creating an
|
||||
* empty DOM document using the specified DOM implementation
|
||||
*/
|
||||
public DomConsumer (Class impl, EventConsumer n)
|
||||
throws SAXException
|
||||
{
|
||||
this (impl);
|
||||
next = n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the document constructed from the preceding
|
||||
* sequence of events. This method should not be
|
||||
* used again until another sequence of events has been
|
||||
* given to this EventConsumer.
|
||||
*/
|
||||
final public Document getDocument ()
|
||||
{
|
||||
return handler.clearDocument ();
|
||||
}
|
||||
|
||||
public void setErrorHandler (ErrorHandler handler)
|
||||
{
|
||||
errHandler = handler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the consumer is hiding entity references nodes
|
||||
* (the default), and false if EntityReference nodes should
|
||||
* instead be created. Such EntityReference nodes will normally be
|
||||
* empty, unless an implementation arranges to populate them and then
|
||||
* turn them back into readonly objects.
|
||||
*
|
||||
* @see #setHidingReferences
|
||||
*/
|
||||
final public boolean isHidingReferences ()
|
||||
{ return hidingReferences; }
|
||||
|
||||
/**
|
||||
* Controls whether the consumer will hide entity expansions,
|
||||
* or will instead mark them with entity reference nodes.
|
||||
*
|
||||
* @see #isHidingReferences
|
||||
* @param flag False if entity reference nodes will appear
|
||||
*/
|
||||
final public void setHidingReferences (boolean flag)
|
||||
{ hidingReferences = flag; }
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the consumer is hiding comments (the default),
|
||||
* and false if they should be placed into the output document.
|
||||
*
|
||||
* @see #setHidingComments
|
||||
*/
|
||||
public final boolean isHidingComments ()
|
||||
{ return hidingComments; }
|
||||
|
||||
/**
|
||||
* Controls whether the consumer is hiding comments.
|
||||
*
|
||||
* @see #isHidingComments
|
||||
*/
|
||||
public final void setHidingComments (boolean flag)
|
||||
{ hidingComments = flag; }
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the consumer is hiding ignorable whitespace
|
||||
* (the default), and false if such whitespace should be placed
|
||||
* into the output document as children of element nodes.
|
||||
*
|
||||
* @see #setHidingWhitespace
|
||||
*/
|
||||
public final boolean isHidingWhitespace ()
|
||||
{ return hidingWhitespace; }
|
||||
|
||||
/**
|
||||
* Controls whether the consumer hides ignorable whitespace
|
||||
*
|
||||
* @see #isHidingComments
|
||||
*/
|
||||
public final void setHidingWhitespace (boolean flag)
|
||||
{ hidingWhitespace = flag; }
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the consumer is saving CDATA boundaries, or
|
||||
* false (the default) otherwise.
|
||||
*
|
||||
* @see #setHidingCDATA
|
||||
*/
|
||||
final public boolean isHidingCDATA ()
|
||||
{ return hidingCDATA; }
|
||||
|
||||
/**
|
||||
* Controls whether the consumer will save CDATA boundaries.
|
||||
*
|
||||
* @see #isHidingCDATA
|
||||
* @param flag True to treat CDATA text differently from other
|
||||
* text nodes
|
||||
*/
|
||||
final public void setHidingCDATA (boolean flag)
|
||||
{ hidingCDATA = flag; }
|
||||
|
||||
|
||||
|
||||
/** Returns the document handler being used. */
|
||||
final public ContentHandler getContentHandler ()
|
||||
{ return handler; }
|
||||
|
||||
/** Returns the DTD handler being used. */
|
||||
final public DTDHandler getDTDHandler ()
|
||||
{ return handler; }
|
||||
|
||||
/**
|
||||
* Returns the lexical handler being used.
|
||||
* (DOM construction can't really use declaration handlers.)
|
||||
*/
|
||||
final public Object getProperty (String id)
|
||||
throws SAXNotRecognizedException
|
||||
{
|
||||
if ("http://xml.org/sax/properties/lexical-handler".equals (id))
|
||||
return handler;
|
||||
if ("http://xml.org/sax/properties/declaration-handler".equals (id))
|
||||
return handler;
|
||||
throw new SAXNotRecognizedException (id);
|
||||
}
|
||||
|
||||
EventConsumer getNext () { return next; }
|
||||
|
||||
ErrorHandler getErrorHandler () { return errHandler; }
|
||||
|
||||
/**
|
||||
* Class used to intercept various parsing events and use them to
|
||||
* populate a DOM document. Subclasses would typically know and use
|
||||
* backdoors into specific DOM implementations, used to implement
|
||||
* DTD-related functionality.
|
||||
*
|
||||
* <p> Note that if this ever throws a DOMException (runtime exception)
|
||||
* that will indicate a bug in the DOM (e.g. doesn't support something
|
||||
* per specification) or the parser (e.g. emitted an illegal name, or
|
||||
* accepted illegal input data). </p>
|
||||
*/
|
||||
public static class Handler
|
||||
implements ContentHandler2, LexicalHandler,
|
||||
DTDHandler, DeclHandler
|
||||
{
|
||||
protected DomConsumer consumer;
|
||||
|
||||
private DOMImplementation impl;
|
||||
private Document document;
|
||||
private boolean isL2;
|
||||
|
||||
private Locator locator;
|
||||
private Node top;
|
||||
private boolean inCDATA;
|
||||
private boolean mergeCDATA;
|
||||
private boolean inDTD;
|
||||
private String currentEntity;
|
||||
|
||||
private boolean recreatedAttrs;
|
||||
private AttributesImpl attributes = new AttributesImpl ();
|
||||
|
||||
/**
|
||||
* Subclasses may use SAX2 events to provide additional
|
||||
* behaviors in the resulting DOM.
|
||||
*/
|
||||
protected Handler (DomConsumer consumer)
|
||||
throws SAXException
|
||||
{
|
||||
this.consumer = consumer;
|
||||
document = consumer.emptyDocument ();
|
||||
impl = document.getImplementation ();
|
||||
isL2 = impl.hasFeature ("XML", "2.0");
|
||||
}
|
||||
|
||||
private void fatal (String message, Exception x)
|
||||
throws SAXException
|
||||
{
|
||||
SAXParseException e;
|
||||
ErrorHandler errHandler = consumer.getErrorHandler ();;
|
||||
|
||||
if (locator == null)
|
||||
e = new SAXParseException (message, null, null, -1, -1, x);
|
||||
else
|
||||
e = new SAXParseException (message, locator, x);
|
||||
if (errHandler != null)
|
||||
errHandler.fatalError (e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and forgets the document produced. If the handler is
|
||||
* reused, a new document may be created.
|
||||
*/
|
||||
Document clearDocument ()
|
||||
{
|
||||
Document retval = document;
|
||||
document = null;
|
||||
locator = null;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the document under construction.
|
||||
*/
|
||||
protected Document getDocument ()
|
||||
{ return document; }
|
||||
|
||||
/**
|
||||
* Returns the current node being populated. This is usually
|
||||
* an Element or Document, but it might be an EntityReference
|
||||
* node if some implementation-specific code knows how to put
|
||||
* those into the result tree and later mark them as readonly.
|
||||
*/
|
||||
protected Node getTop ()
|
||||
{ return top; }
|
||||
|
||||
|
||||
// SAX1
|
||||
public void setDocumentLocator (Locator locator)
|
||||
{
|
||||
this.locator = locator;
|
||||
}
|
||||
|
||||
// SAX1
|
||||
public void startDocument ()
|
||||
throws SAXException
|
||||
{
|
||||
if (document == null)
|
||||
try {
|
||||
if (isL2) {
|
||||
// couple to original implementation
|
||||
document = impl.createDocument (null, "foo", null);
|
||||
document.removeChild (document.getFirstChild ());
|
||||
} else {
|
||||
document = consumer.emptyDocument ();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
fatal ("DOM create document", e);
|
||||
}
|
||||
top = document;
|
||||
}
|
||||
|
||||
// ContentHandler2
|
||||
public void xmlDecl(String version,
|
||||
String encoding,
|
||||
boolean standalone,
|
||||
String inputEncoding)
|
||||
throws SAXException
|
||||
{
|
||||
if (document != null)
|
||||
{
|
||||
document.setXmlVersion(version);
|
||||
document.setXmlStandalone(standalone);
|
||||
}
|
||||
}
|
||||
|
||||
// SAX1
|
||||
public void endDocument ()
|
||||
throws SAXException
|
||||
{
|
||||
try {
|
||||
if (consumer.getNext () != null && document != null) {
|
||||
DomParser parser = new DomParser (document);
|
||||
|
||||
EventFilter.bind (parser, consumer.getNext ());
|
||||
parser.parse ("ignored");
|
||||
}
|
||||
} finally {
|
||||
top = null;
|
||||
}
|
||||
}
|
||||
|
||||
// SAX1
|
||||
public void processingInstruction (String target, String data)
|
||||
throws SAXException
|
||||
{
|
||||
// we can't create populated entity ref nodes using
|
||||
// only public DOM APIs (they've got to be readonly)
|
||||
if (currentEntity != null)
|
||||
return;
|
||||
|
||||
ProcessingInstruction pi;
|
||||
|
||||
if (isL2
|
||||
// && consumer.isUsingNamespaces ()
|
||||
&& target.indexOf (':') != -1)
|
||||
namespaceError (
|
||||
"PI target name is namespace nonconformant: "
|
||||
+ target);
|
||||
if (inDTD)
|
||||
return;
|
||||
pi = document.createProcessingInstruction (target, data);
|
||||
top.appendChild (pi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may overrride this method to provide a more efficient
|
||||
* way to construct text nodes.
|
||||
* Typically, copying the text into a single character array will
|
||||
* be more efficient than doing that as well as allocating other
|
||||
* needed for a String, including an internal StringBuffer.
|
||||
* Those additional memory and CPU costs can be incurred later,
|
||||
* if ever needed.
|
||||
* Unfortunately the standard DOM factory APIs encourage those costs
|
||||
* to be incurred early.
|
||||
*/
|
||||
protected Text createText (
|
||||
boolean isCDATA,
|
||||
char ch [],
|
||||
int start,
|
||||
int length
|
||||
) {
|
||||
String value = new String (ch, start, length);
|
||||
|
||||
if (isCDATA)
|
||||
return document.createCDATASection (value);
|
||||
else
|
||||
return document.createTextNode (value);
|
||||
}
|
||||
|
||||
// SAX1
|
||||
public void characters (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
// we can't create populated entity ref nodes using
|
||||
// only public DOM APIs (they've got to be readonly
|
||||
// at creation time)
|
||||
if (currentEntity != null)
|
||||
return;
|
||||
|
||||
Node lastChild = top.getLastChild ();
|
||||
|
||||
// merge consecutive text or CDATA nodes if appropriate.
|
||||
if (lastChild instanceof Text) {
|
||||
if (consumer.isHidingCDATA ()
|
||||
// consecutive Text content ... always merge
|
||||
|| (!inCDATA
|
||||
&& !(lastChild instanceof CDATASection))
|
||||
// consecutive CDATASection content ... don't
|
||||
// merge between sections, only within them
|
||||
|| (inCDATA && mergeCDATA
|
||||
&& lastChild instanceof CDATASection)
|
||||
) {
|
||||
CharacterData last = (CharacterData) lastChild;
|
||||
String value = new String (ch, start, length);
|
||||
|
||||
last.appendData (value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (inCDATA && !consumer.isHidingCDATA ()) {
|
||||
top.appendChild (createText (true, ch, start, length));
|
||||
mergeCDATA = true;
|
||||
} else
|
||||
top.appendChild (createText (false, ch, start, length));
|
||||
}
|
||||
|
||||
// SAX2
|
||||
public void skippedEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
// this callback is useless except to report errors, since
|
||||
// we can't know if the ref was in content, within an
|
||||
// attribute, within a declaration ... only one of those
|
||||
// cases supports more intelligent action than a panic.
|
||||
fatal ("skipped entity: " + name, null);
|
||||
}
|
||||
|
||||
// SAX2
|
||||
public void startPrefixMapping (String prefix, String uri)
|
||||
throws SAXException
|
||||
{
|
||||
// reconstruct "xmlns" attributes deleted by all
|
||||
// SAX2 parsers without "namespace-prefixes" = true
|
||||
if ("".equals (prefix))
|
||||
attributes.addAttribute ("", "", "xmlns",
|
||||
"CDATA", uri);
|
||||
else
|
||||
attributes.addAttribute ("", "", "xmlns:" + prefix,
|
||||
"CDATA", uri);
|
||||
recreatedAttrs = true;
|
||||
}
|
||||
|
||||
// SAX2
|
||||
public void endPrefixMapping (String prefix)
|
||||
throws SAXException
|
||||
{ }
|
||||
|
||||
// SAX2
|
||||
public void startElement (
|
||||
String uri,
|
||||
String localName,
|
||||
String qName,
|
||||
Attributes atts
|
||||
) throws SAXException
|
||||
{
|
||||
// we can't create populated entity ref nodes using
|
||||
// only public DOM APIs (they've got to be readonly)
|
||||
if (currentEntity != null)
|
||||
return;
|
||||
|
||||
// parser discarded basic information; DOM tree isn't writable
|
||||
// without massaging to assign prefixes to all nodes.
|
||||
// the "NSFilter" class does that massaging.
|
||||
if (qName.length () == 0)
|
||||
qName = localName;
|
||||
|
||||
|
||||
Element element;
|
||||
int length = atts.getLength ();
|
||||
|
||||
if (!isL2) {
|
||||
element = document.createElement (qName);
|
||||
|
||||
// first the explicit attributes ...
|
||||
length = atts.getLength ();
|
||||
for (int i = 0; i < length; i++)
|
||||
element.setAttribute (atts.getQName (i),
|
||||
atts.getValue (i));
|
||||
// ... then any recreated ones (DOM deletes duplicates)
|
||||
if (recreatedAttrs) {
|
||||
recreatedAttrs = false;
|
||||
length = attributes.getLength ();
|
||||
for (int i = 0; i < length; i++)
|
||||
element.setAttribute (attributes.getQName (i),
|
||||
attributes.getValue (i));
|
||||
attributes.clear ();
|
||||
}
|
||||
|
||||
top.appendChild (element);
|
||||
top = element;
|
||||
return;
|
||||
}
|
||||
|
||||
// For an L2 DOM when namespace use is enabled, use
|
||||
// createElementNS/createAttributeNS except when
|
||||
// (a) it's an element in the default namespace, or
|
||||
// (b) it's an attribute with no prefix
|
||||
String namespace;
|
||||
|
||||
if (localName.length () != 0)
|
||||
namespace = (uri.length () == 0) ? null : uri;
|
||||
else
|
||||
namespace = getNamespace (getPrefix (qName), atts);
|
||||
|
||||
if (namespace == null)
|
||||
element = document.createElement (qName);
|
||||
else
|
||||
element = document.createElementNS (namespace, qName);
|
||||
|
||||
populateAttributes (element, atts);
|
||||
if (recreatedAttrs) {
|
||||
recreatedAttrs = false;
|
||||
// ... DOM deletes any duplicates
|
||||
populateAttributes (element, attributes);
|
||||
attributes.clear ();
|
||||
}
|
||||
|
||||
top.appendChild (element);
|
||||
top = element;
|
||||
}
|
||||
|
||||
final static String xmlnsURI = "http://www.w3.org/2000/xmlns/";
|
||||
|
||||
private void populateAttributes (Element element, Attributes attrs)
|
||||
throws SAXParseException
|
||||
{
|
||||
int length = attrs.getLength ();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
String type = attrs.getType (i);
|
||||
String value = attrs.getValue (i);
|
||||
String name = attrs.getQName (i);
|
||||
String local = attrs.getLocalName (i);
|
||||
String uri = attrs.getURI (i);
|
||||
|
||||
// parser discarded basic information, DOM tree isn't writable
|
||||
if (name.length () == 0)
|
||||
name = local;
|
||||
|
||||
// all attribute types other than these three may not
|
||||
// contain scoped names... enumerated attributes get
|
||||
// reported as NMTOKEN, except for NOTATION values
|
||||
if (!("CDATA".equals (type)
|
||||
|| "NMTOKEN".equals (type)
|
||||
|| "NMTOKENS".equals (type))) {
|
||||
if (value.indexOf (':') != -1) {
|
||||
namespaceError (
|
||||
"namespace nonconformant attribute value: "
|
||||
+ "<" + element.getNodeName ()
|
||||
+ " " + name + "='" + value + "' ...>");
|
||||
}
|
||||
}
|
||||
|
||||
// xmlns="" is legal (undoes default NS)
|
||||
// xmlns:foo="" is illegal
|
||||
String prefix = getPrefix (name);
|
||||
String namespace;
|
||||
|
||||
if ("xmlns".equals (prefix)) {
|
||||
if ("".equals (value))
|
||||
namespaceError ("illegal null namespace decl, " + name);
|
||||
namespace = xmlnsURI;
|
||||
} else if ("xmlns".equals (name))
|
||||
namespace = xmlnsURI;
|
||||
|
||||
else if (prefix == null)
|
||||
namespace = null;
|
||||
else if (!"".equals(uri) && uri.length () != 0)
|
||||
namespace = uri;
|
||||
else
|
||||
namespace = getNamespace (prefix, attrs);
|
||||
|
||||
if (namespace == null)
|
||||
element.setAttribute (name, value);
|
||||
else
|
||||
element.setAttributeNS (namespace, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private String getPrefix (String name)
|
||||
{
|
||||
int temp;
|
||||
|
||||
if ((temp = name.indexOf (':')) > 0)
|
||||
return name.substring (0, temp);
|
||||
return null;
|
||||
}
|
||||
|
||||
// used with SAX1-level parser output
|
||||
private String getNamespace (String prefix, Attributes attrs)
|
||||
throws SAXParseException
|
||||
{
|
||||
String namespace;
|
||||
String decl;
|
||||
|
||||
// defaulting
|
||||
if (prefix == null) {
|
||||
decl = "xmlns";
|
||||
namespace = attrs.getValue (decl);
|
||||
if ("".equals (namespace))
|
||||
return null;
|
||||
else if (namespace != null)
|
||||
return namespace;
|
||||
|
||||
// "xmlns" is like a keyword
|
||||
// ... according to the Namespace REC, but DOM L2 CR2+
|
||||
// and Infoset violate that by assigning a namespace.
|
||||
// that conflict is resolved elsewhere.
|
||||
} else if ("xmlns".equals (prefix))
|
||||
return null;
|
||||
|
||||
// "xml" prefix is fixed
|
||||
else if ("xml".equals (prefix))
|
||||
return "http://www.w3.org/XML/1998/namespace";
|
||||
|
||||
// otherwise, expect a declaration
|
||||
else {
|
||||
decl = "xmlns:" + prefix;
|
||||
namespace = attrs.getValue (decl);
|
||||
}
|
||||
|
||||
// if we found a local declaration, great
|
||||
if (namespace != null)
|
||||
return namespace;
|
||||
|
||||
|
||||
// ELSE ... search up the tree we've been building
|
||||
for (Node n = top;
|
||||
n != null && n.getNodeType () != Node.DOCUMENT_NODE;
|
||||
n = (Node) n.getParentNode ()) {
|
||||
if (n.getNodeType () == Node.ENTITY_REFERENCE_NODE)
|
||||
continue;
|
||||
Element e = (Element) n;
|
||||
Attr attr = e.getAttributeNode (decl);
|
||||
if (attr != null)
|
||||
return attr.getNodeValue ();
|
||||
}
|
||||
// see above re "xmlns" as keyword
|
||||
if ("xmlns".equals (decl))
|
||||
return null;
|
||||
|
||||
namespaceError ("Undeclared namespace prefix: " + prefix);
|
||||
return null;
|
||||
}
|
||||
|
||||
// SAX2
|
||||
public void endElement (String uri, String localName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
// we can't create populated entity ref nodes using
|
||||
// only public DOM APIs (they've got to be readonly)
|
||||
if (currentEntity != null)
|
||||
return;
|
||||
|
||||
top = top.getParentNode ();
|
||||
}
|
||||
|
||||
// SAX1 (mandatory reporting if validating)
|
||||
public void ignorableWhitespace (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
if (consumer.isHidingWhitespace ())
|
||||
return;
|
||||
characters (ch, start, length);
|
||||
}
|
||||
|
||||
// SAX2 lexical event
|
||||
public void startCDATA ()
|
||||
throws SAXException
|
||||
{
|
||||
inCDATA = true;
|
||||
// true except for the first fragment of a cdata section
|
||||
mergeCDATA = false;
|
||||
}
|
||||
|
||||
// SAX2 lexical event
|
||||
public void endCDATA ()
|
||||
throws SAXException
|
||||
{
|
||||
inCDATA = false;
|
||||
}
|
||||
|
||||
// SAX2 lexical event
|
||||
//
|
||||
// this SAX2 callback merges two unrelated things:
|
||||
// - Declaration of the root element type ... belongs with
|
||||
// the other DTD declaration methods, NOT HERE.
|
||||
// - IDs for the optional external subset ... belongs here
|
||||
// with other lexical information.
|
||||
//
|
||||
// ...and it doesn't include the internal DTD subset, desired
|
||||
// both to support DOM L2 and to enable "pass through" processing
|
||||
//
|
||||
public void startDTD (String name, String publicId, String SystemId)
|
||||
throws SAXException
|
||||
{
|
||||
// need to filter out comments and PIs within the DTD
|
||||
inDTD = true;
|
||||
}
|
||||
|
||||
// SAX2 lexical event
|
||||
public void endDTD ()
|
||||
throws SAXException
|
||||
{
|
||||
inDTD = false;
|
||||
}
|
||||
|
||||
// SAX2 lexical event
|
||||
public void comment (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
Node comment;
|
||||
|
||||
// we can't create populated entity ref nodes using
|
||||
// only public DOM APIs (they've got to be readonly)
|
||||
if (consumer.isHidingComments ()
|
||||
|| inDTD
|
||||
|| currentEntity != null)
|
||||
return;
|
||||
comment = document.createComment (new String (ch, start, length));
|
||||
top.appendChild (comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* May be overridden by subclasses to return true, indicating
|
||||
* that entity reference nodes can be populated and then made
|
||||
* read-only.
|
||||
*/
|
||||
public boolean canPopulateEntityRefs ()
|
||||
{ return false; }
|
||||
|
||||
// SAX2 lexical event
|
||||
public void startEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
// are we ignoring what would be contents of an
|
||||
// entity ref, since we can't populate it?
|
||||
if (currentEntity != null)
|
||||
return;
|
||||
|
||||
// Are we hiding all entity boundaries?
|
||||
if (consumer.isHidingReferences ())
|
||||
return;
|
||||
|
||||
// SAX2 shows parameter entities; DOM hides them
|
||||
if (name.charAt (0) == '%' || "[dtd]".equals (name))
|
||||
return;
|
||||
|
||||
// Since we can't create a populated entity ref node in any
|
||||
// standard way, we create an unpopulated one.
|
||||
EntityReference ref = document.createEntityReference (name);
|
||||
top.appendChild (ref);
|
||||
top = ref;
|
||||
|
||||
// ... allowing subclasses to populate them
|
||||
if (!canPopulateEntityRefs ())
|
||||
currentEntity = name;
|
||||
}
|
||||
|
||||
// SAX2 lexical event
|
||||
public void endEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
if (name.charAt (0) == '%' || "[dtd]".equals (name))
|
||||
return;
|
||||
if (name.equals (currentEntity))
|
||||
currentEntity = null;
|
||||
if (!consumer.isHidingReferences ())
|
||||
top = top.getParentNode ();
|
||||
}
|
||||
|
||||
|
||||
// SAX1 DTD event
|
||||
public void notationDecl (
|
||||
String name,
|
||||
String publicId, String SystemId
|
||||
) throws SAXException
|
||||
{
|
||||
/* IGNORE -- no public DOM API lets us store these
|
||||
* into the doctype node
|
||||
*/
|
||||
}
|
||||
|
||||
// SAX1 DTD event
|
||||
public void unparsedEntityDecl (
|
||||
String name,
|
||||
String publicId, String SystemId,
|
||||
String notationName
|
||||
) throws SAXException
|
||||
{
|
||||
/* IGNORE -- no public DOM API lets us store these
|
||||
* into the doctype node
|
||||
*/
|
||||
}
|
||||
|
||||
// SAX2 declaration event
|
||||
public void elementDecl (String name, String model)
|
||||
throws SAXException
|
||||
{
|
||||
/* IGNORE -- no content model support in DOM L2 */
|
||||
}
|
||||
|
||||
// SAX2 declaration event
|
||||
public void attributeDecl (
|
||||
String eName,
|
||||
String aName,
|
||||
String type,
|
||||
String mode,
|
||||
String value
|
||||
) throws SAXException
|
||||
{
|
||||
/* IGNORE -- no attribute model support in DOM L2 */
|
||||
}
|
||||
|
||||
// SAX2 declaration event
|
||||
public void internalEntityDecl (String name, String value)
|
||||
throws SAXException
|
||||
{
|
||||
/* IGNORE -- no public DOM API lets us store these
|
||||
* into the doctype node
|
||||
*/
|
||||
}
|
||||
|
||||
// SAX2 declaration event
|
||||
public void externalEntityDecl (
|
||||
String name,
|
||||
String publicId,
|
||||
String SystemId
|
||||
) throws SAXException
|
||||
{
|
||||
/* IGNORE -- no public DOM API lets us store these
|
||||
* into the doctype node
|
||||
*/
|
||||
}
|
||||
|
||||
//
|
||||
// These really should offer the option of nonfatal handling,
|
||||
// like other validity errors, though that would cause major
|
||||
// chaos in the DOM data structures. DOM is already spec'd
|
||||
// to treat many of these as fatal, so this is consistent.
|
||||
//
|
||||
private void namespaceError (String description)
|
||||
throws SAXParseException
|
||||
{
|
||||
SAXParseException err;
|
||||
|
||||
err = new SAXParseException (description, locator);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/* EventConsumer.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import org.xml.sax.*;
|
||||
|
||||
|
||||
/**
|
||||
* Collects the event consumption apparatus of a SAX pipeline stage.
|
||||
* Consumers which permit some handlers or other characteristics to be
|
||||
* configured will provide methods to support that configuration.
|
||||
*
|
||||
* <p> Two important categories of consumers include <em>filters</em>, which
|
||||
* process events and pass them on to other consumers, and <em>terminus</em>
|
||||
* (or <em>terminal</em>) stages, which don't pass events on. Filters are not
|
||||
* necessarily derived from the {@link EventFilter} class, although that
|
||||
* class can substantially simplify their construction by automating the
|
||||
* most common activities.
|
||||
*
|
||||
* <p> Event consumers which follow certain conventions for the signatures
|
||||
* of their constructors can be automatically assembled into pipelines
|
||||
* by the {@link PipelineFactory} class.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public interface EventConsumer
|
||||
{
|
||||
/** Most stages process these core SAX callbacks. */
|
||||
public ContentHandler getContentHandler ();
|
||||
|
||||
/** Few stages will use unparsed entities. */
|
||||
public DTDHandler getDTDHandler ();
|
||||
|
||||
/**
|
||||
* This method works like the SAX2 XMLReader method of the same name,
|
||||
* and is used to retrieve the optional lexical and declaration handlers
|
||||
* in a pipeline.
|
||||
*
|
||||
* @param id This is a URI identifying the type of property desired.
|
||||
* @return The value of that property, if it is defined.
|
||||
*
|
||||
* @exception SAXNotRecognizedException Thrown if the particular
|
||||
* pipeline stage does not understand the specified identifier.
|
||||
*/
|
||||
public Object getProperty (String id)
|
||||
throws SAXNotRecognizedException;
|
||||
|
||||
/**
|
||||
* This method provides a filter stage with a handler that abstracts
|
||||
* presentation of warnings and both recoverable and fatal errors.
|
||||
* Most pipeline stages should share a single policy and mechanism
|
||||
* for such reports, since application components require consistency
|
||||
* in such activities. Accordingly, typical responses to this method
|
||||
* invocation involve saving the handler for use; filters will pass
|
||||
* it on to any other consumers they use.
|
||||
*
|
||||
* @param handler encapsulates error handling policy for this stage
|
||||
*/
|
||||
public void setErrorHandler (ErrorHandler handler);
|
||||
}
|
||||
@@ -0,0 +1,809 @@
|
||||
/* EventFilter.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.ext.*;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
import gnu.xml.aelfred2.ContentHandler2;
|
||||
|
||||
/**
|
||||
* A customizable event consumer, used to assemble various kinds of filters
|
||||
* using SAX handlers and an optional second consumer. It can be constructed
|
||||
* in two ways: <ul>
|
||||
*
|
||||
* <li> To serve as a passthrough, sending all events to a second consumer.
|
||||
* The second consumer may be identified through {@link #getNext}.
|
||||
*
|
||||
* <li> To serve as a dead end, with all handlers null;
|
||||
* {@link #getNext} returns null.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> Additionally, SAX handlers may be assigned, which completely replace
|
||||
* the "upstream" view (through {@link EventConsumer}) of handlers, initially
|
||||
* null or the "next" consumer provided to the constructor. To make
|
||||
* it easier to build specialized filter classes, this class implements
|
||||
* all the standard SAX consumer handlers, and those implementations
|
||||
* delegate "downstream" to the consumer accessed by {@link #getNext}.
|
||||
*
|
||||
* <p> The simplest way to create a custom a filter class is to create a
|
||||
* subclass which overrides one or more handler interface methods. The
|
||||
* constructor for that subclass then registers itself as a handler for
|
||||
* those interfaces using a call such as <em>setContentHandler(this)</em>,
|
||||
* so the "upstream" view of event delivery is modified from the state
|
||||
* established in the base class constructor. That way,
|
||||
* the overridden methods intercept those event callbacks
|
||||
* as they go "downstream", and
|
||||
* all other event callbacks will pass events to any next consumer.
|
||||
* Overridden methods may invoke superclass methods (perhaps after modifying
|
||||
* parameters) if they wish to delegate such calls. Such subclasses
|
||||
* should use {@link #getErrorHandler} to report errors using the
|
||||
* common error reporting mechanism.
|
||||
*
|
||||
* <p> Another important technique is to construct a filter consisting
|
||||
* of only a few specific types of handler. For example, one could easily
|
||||
* prune out lexical events or various declarations by providing handlers
|
||||
* which don't pass those events downstream, or by providing null handlers.
|
||||
*
|
||||
* <hr />
|
||||
*
|
||||
* <p> This may be viewed as the consumer oriented analogue of the SAX2
|
||||
* {@link org.xml.sax.helpers.XMLFilterImpl XMLFilterImpl} class.
|
||||
* Key differences include: <ul>
|
||||
*
|
||||
* <li> This fully separates consumer and producer roles: it
|
||||
* does not implement the producer side <em>XMLReader</em> or
|
||||
* <em>EntityResolver</em> interfaces, so it can only be used
|
||||
* in "push" mode (it has no <em>parse()</em> methods).
|
||||
*
|
||||
* <li> "Extension" handlers are fully supported, enabling a
|
||||
* richer set of application requirements.
|
||||
* And it implements {@link EventConsumer}, which groups related
|
||||
* consumer methods together, rather than leaving them separated.
|
||||
*
|
||||
* <li> The chaining which is visible is "downstream" to the next
|
||||
* consumer, not "upstream" to the preceding producer.
|
||||
* It supports "fan-in", where
|
||||
* a consumer can be fed by several producers. (For "fan-out",
|
||||
* see the {@link TeeConsumer} class.)
|
||||
*
|
||||
* <li> Event chaining is set up differently. It is intended to
|
||||
* work "upstream" from terminus towards producer, during filter
|
||||
* construction, as described above.
|
||||
* This is part of an early binding model:
|
||||
* events don't need to pass through stages which ignore them.
|
||||
*
|
||||
* <li> ErrorHandler support is separated, on the grounds that
|
||||
* pipeline stages need to share the same error handling policy.
|
||||
* For the same reason, error handler setup goes "downstream":
|
||||
* when error handlers get set, they are passed to subsequent
|
||||
* consumers.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> The {@link #chainTo chainTo()} convenience routine supports chaining to
|
||||
* an XMLFilterImpl, in its role as a limited functionality event
|
||||
* consumer. Its event producer role ({@link XMLFilter}) is ignored.
|
||||
*
|
||||
* <hr />
|
||||
*
|
||||
* <p> The {@link #bind bind()} routine may be used associate event pipelines
|
||||
* with any kind of {@link XMLReader} that will produce the events.
|
||||
* Such pipelines don't necessarily need to have any members which are
|
||||
* implemented using this class. That routine has some intelligence
|
||||
* which supports automatic changes to parser feature flags, letting
|
||||
* event piplines become largely independent of the particular feature
|
||||
* sets of parsers.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class EventFilter
|
||||
implements EventConsumer, ContentHandler2, DTDHandler,
|
||||
LexicalHandler, DeclHandler
|
||||
{
|
||||
// SAX handlers
|
||||
private ContentHandler docHandler, docNext;
|
||||
private DTDHandler dtdHandler, dtdNext;
|
||||
private LexicalHandler lexHandler, lexNext;
|
||||
private DeclHandler declHandler, declNext;
|
||||
// and ideally, one more for the stuff SAX2 doesn't show
|
||||
|
||||
private Locator locator;
|
||||
private EventConsumer next;
|
||||
private ErrorHandler errHandler;
|
||||
|
||||
|
||||
/** SAX2 URI prefix for standard feature flags. */
|
||||
public static final String FEATURE_URI
|
||||
= "http://xml.org/sax/features/";
|
||||
/** SAX2 URI prefix for standard properties (mostly for handlers). */
|
||||
public static final String PROPERTY_URI
|
||||
= "http://xml.org/sax/properties/";
|
||||
|
||||
/** SAX2 property identifier for {@link DeclHandler} events */
|
||||
public static final String DECL_HANDLER
|
||||
= PROPERTY_URI + "declaration-handler";
|
||||
/** SAX2 property identifier for {@link LexicalHandler} events */
|
||||
public static final String LEXICAL_HANDLER
|
||||
= PROPERTY_URI + "lexical-handler";
|
||||
|
||||
//
|
||||
// These class objects will be null if the relevant class isn't linked.
|
||||
// Small configurations (pJava and some kinds of embedded systems) need
|
||||
// to facilitate smaller executables. So "instanceof" is undesirable
|
||||
// when bind() sees if it can remove some stages.
|
||||
//
|
||||
// SECURITY NOTE: assuming all these classes are part of the same sealed
|
||||
// package, there's no problem saving these in the instance of this class
|
||||
// that's associated with "this" class loader. But that wouldn't be true
|
||||
// for classes in another package.
|
||||
//
|
||||
private static boolean loaded;
|
||||
private static Class nsClass;
|
||||
private static Class validClass;
|
||||
private static Class wfClass;
|
||||
private static Class xincClass;
|
||||
|
||||
static ClassLoader getClassLoader ()
|
||||
{
|
||||
Method m = null;
|
||||
|
||||
try {
|
||||
m = Thread.class.getMethod("getContextClassLoader", null);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Assume that we are running JDK 1.1, use the current ClassLoader
|
||||
return EventFilter.class.getClassLoader();
|
||||
}
|
||||
|
||||
try {
|
||||
return (ClassLoader) m.invoke(Thread.currentThread(), null);
|
||||
} catch (IllegalAccessException e) {
|
||||
// assert(false)
|
||||
throw new UnknownError(e.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
// assert(e.getTargetException() instanceof SecurityException)
|
||||
throw new UnknownError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static Class loadClass (ClassLoader classLoader, String className)
|
||||
{
|
||||
try {
|
||||
if (classLoader == null)
|
||||
return Class.forName(className);
|
||||
else
|
||||
return classLoader.loadClass(className);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static private void loadClasses ()
|
||||
{
|
||||
ClassLoader loader = getClassLoader ();
|
||||
|
||||
nsClass = loadClass (loader, "gnu.xml.pipeline.NSFilter");
|
||||
validClass = loadClass (loader, "gnu.xml.pipeline.ValidationConsumer");
|
||||
wfClass = loadClass (loader, "gnu.xml.pipeline.WellFormednessFilter");
|
||||
xincClass = loadClass (loader, "gnu.xml.pipeline.XIncludeFilter");
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Binds the standard SAX2 handlers from the specified consumer
|
||||
* pipeline to the specified producer. These handlers include the core
|
||||
* {@link ContentHandler} and {@link DTDHandler}, plus the extension
|
||||
* {@link DeclHandler} and {@link LexicalHandler}. Any additional
|
||||
* application-specific handlers need to be bound separately.
|
||||
* The {@link ErrorHandler} is handled differently: the producer's
|
||||
* error handler is passed through to the consumer pipeline.
|
||||
* The producer is told to include namespace prefix information if it
|
||||
* can, since many pipeline stages need that Infoset information to
|
||||
* work well.
|
||||
*
|
||||
* <p> At the head of the pipeline, certain standard event filters are
|
||||
* recognized and handled specially. This facilitates construction
|
||||
* of processing pipelines that work regardless of the capabilities
|
||||
* of the XMLReader implementation in use; for example, it permits
|
||||
* validating output of a {@link gnu.xml.util.DomParser}. <ul>
|
||||
*
|
||||
* <li> {@link NSFilter} will be removed if the producer can be
|
||||
* told not to discard namespace data, using the "namespace-prefixes"
|
||||
* feature flag.
|
||||
*
|
||||
* <li> {@link ValidationConsumer} will be removed if the producer
|
||||
* can be told to validate, using the "validation" feature flag.
|
||||
*
|
||||
* <li> {@link WellFormednessFilter} is always removed, on the
|
||||
* grounds that no XMLReader is permitted to producee malformed
|
||||
* event streams and this would just be processing overhead.
|
||||
*
|
||||
* <li> {@link XIncludeFilter} stops the special handling, except
|
||||
* that it's told about the "namespace-prefixes" feature of the
|
||||
* event producer so that the event stream is internally consistent.
|
||||
*
|
||||
* <li> The first consumer which is not one of those classes stops
|
||||
* such special handling. This means that if you want to force
|
||||
* one of those filters to be used, you could just precede it with
|
||||
* an instance of {@link EventFilter} configured as a pass-through.
|
||||
* You might need to do that if you are using an {@link NSFilter}
|
||||
* subclass to fix names found in attributes or character data.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> Other than that, this method works with any kind of event consumer,
|
||||
* not just event filters. Note that in all cases, the standard handlers
|
||||
* are assigned; any previous handler assignments for the handler will
|
||||
* be overridden.
|
||||
*
|
||||
* @param producer will deliver events to the specified consumer
|
||||
* @param consumer pipeline supplying event handlers to be associated
|
||||
* with the producer (may not be null)
|
||||
*/
|
||||
public static void bind (XMLReader producer, EventConsumer consumer)
|
||||
{
|
||||
Class klass = null;
|
||||
boolean prefixes;
|
||||
|
||||
if (!loaded)
|
||||
loadClasses ();
|
||||
|
||||
// DOM building, printing, layered validation, and other
|
||||
// things don't work well when prefix info is discarded.
|
||||
// Include it by default, whenever possible.
|
||||
try {
|
||||
producer.setFeature (FEATURE_URI + "namespace-prefixes",
|
||||
true);
|
||||
prefixes = true;
|
||||
} catch (SAXException e) {
|
||||
prefixes = false;
|
||||
}
|
||||
|
||||
// NOTE: This loop doesn't use "instanceof", since that
|
||||
// would prevent compiling/linking without those classes
|
||||
// being present.
|
||||
while (consumer != null) {
|
||||
klass = consumer.getClass ();
|
||||
|
||||
// we might have already changed this problematic SAX2 default.
|
||||
if (nsClass != null && nsClass.isAssignableFrom (klass)) {
|
||||
if (!prefixes)
|
||||
break;
|
||||
consumer = ((EventFilter)consumer).getNext ();
|
||||
|
||||
// the parser _might_ do DTD validation by default ...
|
||||
// if not, maybe we can change this setting.
|
||||
} else if (validClass != null
|
||||
&& validClass.isAssignableFrom (klass)) {
|
||||
try {
|
||||
producer.setFeature (FEATURE_URI + "validation",
|
||||
true);
|
||||
consumer = ((ValidationConsumer)consumer).getNext ();
|
||||
} catch (SAXException e) {
|
||||
break;
|
||||
}
|
||||
|
||||
// parsers are required not to have such bugs
|
||||
} else if (wfClass != null && wfClass.isAssignableFrom (klass)) {
|
||||
consumer = ((WellFormednessFilter)consumer).getNext ();
|
||||
|
||||
// stop on the first pipeline stage we can't remove
|
||||
} else
|
||||
break;
|
||||
|
||||
if (consumer == null)
|
||||
klass = null;
|
||||
}
|
||||
|
||||
// the actual setting here doesn't matter as much
|
||||
// as that producer and consumer agree
|
||||
if (xincClass != null && klass != null
|
||||
&& xincClass.isAssignableFrom (klass))
|
||||
((XIncludeFilter)consumer).setSavingPrefixes (prefixes);
|
||||
|
||||
// Some SAX parsers can't handle null handlers -- bleech
|
||||
DefaultHandler2 h = new DefaultHandler2 ();
|
||||
|
||||
if (consumer != null && consumer.getContentHandler () != null)
|
||||
producer.setContentHandler (consumer.getContentHandler ());
|
||||
else
|
||||
producer.setContentHandler (h);
|
||||
if (consumer != null && consumer.getDTDHandler () != null)
|
||||
producer.setDTDHandler (consumer.getDTDHandler ());
|
||||
else
|
||||
producer.setDTDHandler (h);
|
||||
|
||||
try {
|
||||
Object dh;
|
||||
|
||||
if (consumer != null)
|
||||
dh = consumer.getProperty (DECL_HANDLER);
|
||||
else
|
||||
dh = null;
|
||||
if (dh == null)
|
||||
dh = h;
|
||||
producer.setProperty (DECL_HANDLER, dh);
|
||||
} catch (Exception e) { /* ignore */ }
|
||||
try {
|
||||
Object lh;
|
||||
|
||||
if (consumer != null)
|
||||
lh = consumer.getProperty (LEXICAL_HANDLER);
|
||||
else
|
||||
lh = null;
|
||||
if (lh == null)
|
||||
lh = h;
|
||||
producer.setProperty (LEXICAL_HANDLER, lh);
|
||||
} catch (Exception e) { /* ignore */ }
|
||||
|
||||
// this binding goes the other way around
|
||||
if (producer.getErrorHandler () == null)
|
||||
producer.setErrorHandler (h);
|
||||
if (consumer != null)
|
||||
consumer.setErrorHandler (producer.getErrorHandler ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes all handlers to null.
|
||||
*/
|
||||
// constructor used by PipelineFactory
|
||||
public EventFilter () { }
|
||||
|
||||
|
||||
/**
|
||||
* Handlers that are not otherwise set will default to those from
|
||||
* the specified consumer, making it easy to pass events through.
|
||||
* If the consumer is null, all handlers are initialzed to null.
|
||||
*/
|
||||
// constructor used by PipelineFactory
|
||||
public EventFilter (EventConsumer consumer)
|
||||
{
|
||||
if (consumer == null)
|
||||
return;
|
||||
|
||||
next = consumer;
|
||||
|
||||
// We delegate through the "xxNext" handlers, and
|
||||
// report the "xxHandler" ones on our input side.
|
||||
|
||||
// Normally a subclass would both override handler
|
||||
// methods and register itself as the "xxHandler".
|
||||
|
||||
docHandler = docNext = consumer.getContentHandler ();
|
||||
dtdHandler = dtdNext = consumer.getDTDHandler ();
|
||||
try {
|
||||
declHandler = declNext = (DeclHandler)
|
||||
consumer.getProperty (DECL_HANDLER);
|
||||
} catch (SAXException e) { /* leave value null */ }
|
||||
try {
|
||||
lexHandler = lexNext = (LexicalHandler)
|
||||
consumer.getProperty (LEXICAL_HANDLER);
|
||||
} catch (SAXException e) { /* leave value null */ }
|
||||
}
|
||||
|
||||
/**
|
||||
* Treats the XMLFilterImpl as a limited functionality event consumer,
|
||||
* by arranging to deliver events to it; this lets such classes be
|
||||
* "wrapped" as pipeline stages.
|
||||
*
|
||||
* <p> <em>Upstream Event Setup:</em>
|
||||
* If no handlers have been assigned to this EventFilter, then the
|
||||
* handlers from specified XMLFilterImpl are returned from this
|
||||
* {@link EventConsumer}: the XMLFilterImpl is just "wrapped".
|
||||
* Otherwise the specified handlers will be returned.
|
||||
*
|
||||
* <p> <em>Downstream Event Setup:</em>
|
||||
* Subclasses may chain event delivery to the specified XMLFilterImpl
|
||||
* by invoking the appropiate superclass methods,
|
||||
* as if their constructor passed a "next" EventConsumer to the
|
||||
* constructor for this class.
|
||||
* If this EventFilter has an ErrorHandler, it is assigned as
|
||||
* the error handler for the XMLFilterImpl, just as would be
|
||||
* done for a next stage implementing {@link EventConsumer}.
|
||||
*
|
||||
* @param next the next downstream component of the pipeline.
|
||||
* @exception IllegalStateException if the "next" consumer has
|
||||
* already been set through the constructor.
|
||||
*/
|
||||
public void chainTo (XMLFilterImpl next)
|
||||
{
|
||||
if (this.next != null)
|
||||
throw new IllegalStateException ();
|
||||
|
||||
docNext = next.getContentHandler ();
|
||||
if (docHandler == null)
|
||||
docHandler = docNext;
|
||||
dtdNext = next.getDTDHandler ();
|
||||
if (dtdHandler == null)
|
||||
dtdHandler = dtdNext;
|
||||
|
||||
try {
|
||||
declNext = (DeclHandler) next.getProperty (DECL_HANDLER);
|
||||
if (declHandler == null)
|
||||
declHandler = declNext;
|
||||
} catch (SAXException e) { /* leave value null */ }
|
||||
try {
|
||||
lexNext = (LexicalHandler) next.getProperty (LEXICAL_HANDLER);
|
||||
if (lexHandler == null)
|
||||
lexHandler = lexNext;
|
||||
} catch (SAXException e) { /* leave value null */ }
|
||||
|
||||
if (errHandler != null)
|
||||
next.setErrorHandler (errHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the error handler that should be used by this stage, and
|
||||
* passes it "downstream" to any subsequent stage.
|
||||
*/
|
||||
final public void setErrorHandler (ErrorHandler handler)
|
||||
{
|
||||
errHandler = handler;
|
||||
if (next != null)
|
||||
next.setErrorHandler (handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error handler assigned this filter stage, or null
|
||||
* if no such assigment has been made.
|
||||
*/
|
||||
final public ErrorHandler getErrorHandler ()
|
||||
{
|
||||
return errHandler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next event consumer in sequence; or null if there
|
||||
* is no such handler.
|
||||
*/
|
||||
final public EventConsumer getNext ()
|
||||
{ return next; }
|
||||
|
||||
|
||||
/**
|
||||
* Assigns the content handler to use; a null handler indicates
|
||||
* that these events will not be forwarded.
|
||||
* This overrides the previous settting for this handler, which was
|
||||
* probably pointed to the next consumer by the base class constructor.
|
||||
*/
|
||||
final public void setContentHandler (ContentHandler h)
|
||||
{
|
||||
docHandler = h;
|
||||
}
|
||||
|
||||
/** Returns the content handler being used. */
|
||||
final public ContentHandler getContentHandler ()
|
||||
{
|
||||
return docHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the DTD handler to use; a null handler indicates
|
||||
* that these events will not be forwarded.
|
||||
* This overrides the previous settting for this handler, which was
|
||||
* probably pointed to the next consumer by the base class constructor.
|
||||
*/
|
||||
final public void setDTDHandler (DTDHandler h)
|
||||
{ dtdHandler = h; }
|
||||
|
||||
/** Returns the dtd handler being used. */
|
||||
final public DTDHandler getDTDHandler ()
|
||||
{
|
||||
return dtdHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the property, normally a handler; a null handler indicates
|
||||
* that these events will not be forwarded.
|
||||
* This overrides the previous handler settting, which was probably
|
||||
* pointed to the next consumer by the base class constructor.
|
||||
*/
|
||||
final public void setProperty (String id, Object o)
|
||||
throws SAXNotRecognizedException, SAXNotSupportedException
|
||||
{
|
||||
try {
|
||||
Object value = getProperty (id);
|
||||
|
||||
if (value == o)
|
||||
return;
|
||||
if (DECL_HANDLER.equals (id)) {
|
||||
declHandler = (DeclHandler) o;
|
||||
return;
|
||||
}
|
||||
if (LEXICAL_HANDLER.equals (id)) {
|
||||
lexHandler = (LexicalHandler) o;
|
||||
return;
|
||||
}
|
||||
throw new SAXNotSupportedException (id);
|
||||
|
||||
} catch (ClassCastException e) {
|
||||
throw new SAXNotSupportedException (id);
|
||||
}
|
||||
}
|
||||
|
||||
/** Retrieves a property of unknown intent (usually a handler) */
|
||||
final public Object getProperty (String id)
|
||||
throws SAXNotRecognizedException
|
||||
{
|
||||
if (DECL_HANDLER.equals (id))
|
||||
return declHandler;
|
||||
if (LEXICAL_HANDLER.equals (id))
|
||||
return lexHandler;
|
||||
|
||||
throw new SAXNotRecognizedException (id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any locator provided to the next consumer, if this class
|
||||
* (or a subclass) is handling {@link ContentHandler } events.
|
||||
*/
|
||||
public Locator getDocumentLocator ()
|
||||
{ return locator; }
|
||||
|
||||
|
||||
// CONTENT HANDLER DELEGATIONS
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void setDocumentLocator (Locator locator)
|
||||
{
|
||||
this.locator = locator;
|
||||
if (docNext != null)
|
||||
docNext.setDocumentLocator (locator);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void startDocument () throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.startDocument ();
|
||||
}
|
||||
|
||||
public void xmlDecl(String version, String encoding, boolean standalone,
|
||||
String inputEncoding)
|
||||
throws SAXException
|
||||
{
|
||||
if (docNext != null && docNext instanceof ContentHandler2)
|
||||
{
|
||||
((ContentHandler2) docNext).xmlDecl(version, encoding, standalone,
|
||||
inputEncoding);
|
||||
}
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void skippedEntity (String name) throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.skippedEntity (name);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void processingInstruction (String target, String data)
|
||||
throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.processingInstruction (target, data);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void characters (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.characters (ch, start, length);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void ignorableWhitespace (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.ignorableWhitespace (ch, start, length);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void startPrefixMapping (String prefix, String uri)
|
||||
throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.startPrefixMapping (prefix, uri);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void startElement (
|
||||
String uri, String localName,
|
||||
String qName, Attributes atts
|
||||
) throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.startElement (uri, localName, qName, atts);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void endElement (String uri, String localName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.endElement (uri, localName, qName);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void endPrefixMapping (String prefix) throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.endPrefixMapping (prefix);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
if (docNext != null)
|
||||
docNext.endDocument ();
|
||||
locator = null;
|
||||
}
|
||||
|
||||
|
||||
// DTD HANDLER DELEGATIONS
|
||||
|
||||
/** <b>SAX1:</b> passes this callback to the next consumer, if any */
|
||||
public void unparsedEntityDecl (
|
||||
String name,
|
||||
String publicId,
|
||||
String systemId,
|
||||
String notationName
|
||||
) throws SAXException
|
||||
{
|
||||
if (dtdNext != null)
|
||||
dtdNext.unparsedEntityDecl (name, publicId, systemId, notationName);
|
||||
}
|
||||
|
||||
/** <b>SAX1:</b> passes this callback to the next consumer, if any */
|
||||
public void notationDecl (String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (dtdNext != null)
|
||||
dtdNext.notationDecl (name, publicId, systemId);
|
||||
}
|
||||
|
||||
|
||||
// LEXICAL HANDLER DELEGATIONS
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void startDTD (String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (lexNext != null)
|
||||
lexNext.startDTD (name, publicId, systemId);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void endDTD ()
|
||||
throws SAXException
|
||||
{
|
||||
if (lexNext != null)
|
||||
lexNext.endDTD ();
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void comment (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
if (lexNext != null)
|
||||
lexNext.comment (ch, start, length);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void startCDATA ()
|
||||
throws SAXException
|
||||
{
|
||||
if (lexNext != null)
|
||||
lexNext.startCDATA ();
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void endCDATA ()
|
||||
throws SAXException
|
||||
{
|
||||
if (lexNext != null)
|
||||
lexNext.endCDATA ();
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2:</b> passes this callback to the next consumer, if any.
|
||||
*/
|
||||
public void startEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
if (lexNext != null)
|
||||
lexNext.startEntity (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>SAX2:</b> passes this callback to the next consumer, if any.
|
||||
*/
|
||||
public void endEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
if (lexNext != null)
|
||||
lexNext.endEntity (name);
|
||||
}
|
||||
|
||||
|
||||
// DECLARATION HANDLER DELEGATIONS
|
||||
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void elementDecl (String name, String model)
|
||||
throws SAXException
|
||||
{
|
||||
if (declNext != null)
|
||||
declNext.elementDecl (name, model);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void attributeDecl (String eName, String aName,
|
||||
String type, String mode, String value)
|
||||
throws SAXException
|
||||
{
|
||||
if (declNext != null)
|
||||
declNext.attributeDecl (eName, aName, type, mode, value);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void externalEntityDecl (String name,
|
||||
String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (declNext != null)
|
||||
declNext.externalEntityDecl (name, publicId, systemId);
|
||||
}
|
||||
|
||||
/** <b>SAX2:</b> passes this callback to the next consumer, if any */
|
||||
public void internalEntityDecl (String name, String value)
|
||||
throws SAXException
|
||||
{
|
||||
if (declNext != null)
|
||||
declNext.internalEntityDecl (name, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/* LinkFilter.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
|
||||
/**
|
||||
* Pipeline filter to remember XHTML links found in a document,
|
||||
* so they can later be crawled. Fragments are not counted, and duplicates
|
||||
* are ignored. Callers are responsible for filtering out URLs they aren't
|
||||
* interested in. Events are passed through unmodified.
|
||||
*
|
||||
* <p> Input MUST include a setDocumentLocator() call, as it's used to
|
||||
* resolve relative links in the absence of a "base" element. Input MUST
|
||||
* also include namespace identifiers, since it is the XHTML namespace
|
||||
* identifier which is used to identify the relevant elements.
|
||||
*
|
||||
* <p><em>FIXME:</em> handle xml:base attribute ... in association with
|
||||
* a stack of base URIs. Similarly, recognize/support XLink data.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class LinkFilter extends EventFilter
|
||||
{
|
||||
// for storing URIs
|
||||
private Vector vector = new Vector ();
|
||||
|
||||
// struct for "full" link record (tbd)
|
||||
// these for troubleshooting original source:
|
||||
// original uri
|
||||
// uri as resolved (base, relative, etc)
|
||||
// URI of originating doc
|
||||
// line #
|
||||
// original element + attrs (img src, desc, etc)
|
||||
|
||||
// XLink model of the link ... for inter-site pairups ?
|
||||
|
||||
private String baseURI;
|
||||
|
||||
private boolean siteRestricted = false;
|
||||
|
||||
//
|
||||
// XXX leverage blacklist info (like robots.txt)
|
||||
//
|
||||
// XXX constructor w/param ... pipeline for sending link data
|
||||
// probably XHTML --> XLink, providing info as sketched above
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new event filter, which collects links in private data
|
||||
* structure for later enumeration.
|
||||
*/
|
||||
// constructor used by PipelineFactory
|
||||
public LinkFilter ()
|
||||
{
|
||||
super.setContentHandler (this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new event filter, which collects links in private data
|
||||
* structure for later enumeration and passes all events, unmodified,
|
||||
* to the next consumer.
|
||||
*/
|
||||
// constructor used by PipelineFactory
|
||||
public LinkFilter (EventConsumer next)
|
||||
{
|
||||
super (next);
|
||||
super.setContentHandler (this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an enumeration of the links found since the filter
|
||||
* was constructed, or since removeAllLinks() was called.
|
||||
*
|
||||
* @return enumeration of strings.
|
||||
*/
|
||||
public Enumeration getLinks ()
|
||||
{
|
||||
return vector.elements ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes records about all links reported to the event
|
||||
* stream, as if the filter were newly created.
|
||||
*/
|
||||
public void removeAllLinks ()
|
||||
{
|
||||
vector = new Vector ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collects URIs for (X)HTML content from elements which hold them.
|
||||
*/
|
||||
public void startElement (
|
||||
String uri,
|
||||
String localName,
|
||||
String qName,
|
||||
Attributes atts
|
||||
) throws SAXException
|
||||
{
|
||||
String link;
|
||||
|
||||
// Recognize XHTML links.
|
||||
if ("http://www.w3.org/1999/xhtml".equals (uri)) {
|
||||
|
||||
if ("a".equals (localName) || "base".equals (localName)
|
||||
|| "area".equals (localName))
|
||||
link = atts.getValue ("href");
|
||||
else if ("iframe".equals (localName) || "frame".equals (localName))
|
||||
link = atts.getValue ("src");
|
||||
else if ("blockquote".equals (localName) || "q".equals (localName)
|
||||
|| "ins".equals (localName) || "del".equals (localName))
|
||||
link = atts.getValue ("cite");
|
||||
else
|
||||
link = null;
|
||||
link = maybeAddLink (link);
|
||||
|
||||
// "base" modifies designated baseURI
|
||||
if ("base".equals (localName) && link != null)
|
||||
baseURI = link;
|
||||
|
||||
if ("iframe".equals (localName) || "img".equals (localName))
|
||||
maybeAddLink (atts.getValue ("longdesc"));
|
||||
}
|
||||
|
||||
super.startElement (uri, localName, qName, atts);
|
||||
}
|
||||
|
||||
private String maybeAddLink (String link)
|
||||
{
|
||||
int index;
|
||||
|
||||
// ignore empty links and fragments inside docs
|
||||
if (link == null)
|
||||
return null;
|
||||
if ((index = link.indexOf ("#")) >= 0)
|
||||
link = link.substring (0, index);
|
||||
if (link.equals (""))
|
||||
return null;
|
||||
|
||||
try {
|
||||
// get the real URI
|
||||
URL base = new URL ((baseURI != null)
|
||||
? baseURI
|
||||
: getDocumentLocator ().getSystemId ());
|
||||
URL url = new URL (base, link);
|
||||
|
||||
link = url.toString ();
|
||||
|
||||
// ignore duplicates
|
||||
if (vector.contains (link))
|
||||
return link;
|
||||
|
||||
// other than what "base" does, stick to original site:
|
||||
if (siteRestricted) {
|
||||
// don't switch protocols
|
||||
if (!base.getProtocol ().equals (url.getProtocol ()))
|
||||
return link;
|
||||
// don't switch servers
|
||||
if (base.getHost () != null
|
||||
&& !base.getHost ().equals (url.getHost ()))
|
||||
return link;
|
||||
}
|
||||
|
||||
vector.addElement (link);
|
||||
|
||||
return link;
|
||||
|
||||
} catch (IOException e) {
|
||||
// bad URLs we don't want
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports an error if no Locator has been made available.
|
||||
*/
|
||||
public void startDocument ()
|
||||
throws SAXException
|
||||
{
|
||||
if (getDocumentLocator () == null)
|
||||
throw new SAXException ("no Locator!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Forgets about any base URI information that may be recorded.
|
||||
* Applications will often want to call removeAllLinks(), likely
|
||||
* after examining the links which were reported.
|
||||
*/
|
||||
public void endDocument ()
|
||||
throws SAXException
|
||||
{
|
||||
baseURI = null;
|
||||
super.endDocument ();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
/* NSFilter.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.ext.*;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
import org.xml.sax.helpers.NamespaceSupport;
|
||||
|
||||
|
||||
/**
|
||||
* This filter ensures that element and attribute names are properly prefixed,
|
||||
* and that such prefixes are declared. Such data is critical for operations
|
||||
* like writing XML text, and validating against DTDs: names or their prefixes
|
||||
* may have been discarded, although they are essential to the exchange of
|
||||
* information using XML. There are various common ways that such data
|
||||
* gets discarded: <ul>
|
||||
*
|
||||
* <li> By default, SAX2 parsers must discard the "xmlns*"
|
||||
* attributes, and may also choose not to report properly prefixed
|
||||
* names for elements or attributes. (Some parsers may support
|
||||
* changing the <em>namespace-prefixes</em> value from the default
|
||||
* to <em>true</em>, effectively eliminating the need to use this
|
||||
* filter on their output.)
|
||||
*
|
||||
* <li> When event streams are generated from a DOM tree, they may
|
||||
* have never have had prefixes or declarations for namespaces; or
|
||||
* the existing prefixes or declarations may have been invalidated
|
||||
* by structural modifications to that DOM tree.
|
||||
*
|
||||
* <li> Other software writing SAX event streams won't necessarily
|
||||
* be worrying about prefix management, and so they will need to
|
||||
* have a transparent solution for managing them.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> This filter uses a heuristic to choose the prefix to assign to any
|
||||
* particular name which wasn't already corectly prefixed. The associated
|
||||
* namespace will be correct, and the prefix will be declared. Original
|
||||
* structures facilitating text editing, such as conventions about use of
|
||||
* mnemonic prefix names or the scoping of prefixes, can't always be
|
||||
* reconstructed after they are discarded, as strongly encouraged by the
|
||||
* current SAX2 defaults.
|
||||
*
|
||||
* <p> Note that this can't possibly know whether values inside attribute
|
||||
* value or document content involve prefixed names. If your application
|
||||
* requires using prefixed names in such locations you'll need to add some
|
||||
* appropriate logic (perhaps adding additional heuristics in a subclass).
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class NSFilter extends EventFilter
|
||||
{
|
||||
private NamespaceSupport nsStack = new NamespaceSupport ();
|
||||
private Stack elementStack = new Stack ();
|
||||
|
||||
private boolean pushedContext;
|
||||
private String nsTemp [] = new String [3];
|
||||
private AttributesImpl attributes = new AttributesImpl ();
|
||||
private boolean usedDefault;
|
||||
|
||||
// gensymmed prefixes use this root name
|
||||
private static final String prefixRoot = "prefix-";
|
||||
|
||||
|
||||
/**
|
||||
* Passes events through to the specified consumer, after first
|
||||
* processing them.
|
||||
*
|
||||
* @param next the next event consumer to receive events.
|
||||
*/
|
||||
// constructor used by PipelineFactory
|
||||
public NSFilter (EventConsumer next)
|
||||
{
|
||||
super (next);
|
||||
|
||||
setContentHandler (this);
|
||||
}
|
||||
|
||||
private void fatalError (String message)
|
||||
throws SAXException
|
||||
{
|
||||
SAXParseException e;
|
||||
ErrorHandler handler = getErrorHandler ();
|
||||
Locator locator = getDocumentLocator ();
|
||||
|
||||
if (locator == null)
|
||||
e = new SAXParseException (message, null, null, -1, -1);
|
||||
else
|
||||
e = new SAXParseException (message, locator);
|
||||
if (handler != null)
|
||||
handler.fatalError (e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
public void startDocument () throws SAXException
|
||||
{
|
||||
elementStack.removeAllElements ();
|
||||
nsStack.reset ();
|
||||
pushedContext = false;
|
||||
super.startDocument ();
|
||||
}
|
||||
|
||||
/**
|
||||
* This call is not passed to the next consumer in the chain.
|
||||
* Prefix declarations and scopes are only exposed in the form
|
||||
* of attributes; this callback just records a declaration that
|
||||
* will be exposed as an attribute.
|
||||
*/
|
||||
public void startPrefixMapping (String prefix, String uri)
|
||||
throws SAXException
|
||||
{
|
||||
if (pushedContext == false) {
|
||||
nsStack.pushContext ();
|
||||
pushedContext = true;
|
||||
}
|
||||
|
||||
// this check is awkward, but the paranoia prevents big trouble
|
||||
for (Enumeration e = nsStack.getDeclaredPrefixes ();
|
||||
e.hasMoreElements ();
|
||||
/* NOP */ ) {
|
||||
String declared = (String) e.nextElement ();
|
||||
|
||||
if (!declared.equals (prefix))
|
||||
continue;
|
||||
if (uri.equals (nsStack.getURI (prefix)))
|
||||
return;
|
||||
fatalError ("inconsistent binding for prefix '" + prefix
|
||||
+ "' ... " + uri + " (was " + nsStack.getURI (prefix) + ")");
|
||||
}
|
||||
|
||||
if (!nsStack.declarePrefix (prefix, uri))
|
||||
fatalError ("illegal prefix declared: " + prefix);
|
||||
}
|
||||
|
||||
private String fixName (String ns, String l, String name, boolean isAttr)
|
||||
throws SAXException
|
||||
{
|
||||
if ("".equals (name) || name == null) {
|
||||
name = l;
|
||||
if ("".equals (name) || name == null)
|
||||
fatalError ("empty/null name");
|
||||
}
|
||||
|
||||
// can we correctly process the name as-is?
|
||||
// handles "element scope" attribute names here.
|
||||
if (nsStack.processName (name, nsTemp, isAttr) != null
|
||||
&& nsTemp [0].equals (ns)
|
||||
) {
|
||||
return nsTemp [2];
|
||||
}
|
||||
|
||||
// nope, gotta modify the name or declare a default mapping
|
||||
int temp;
|
||||
|
||||
// get rid of any current prefix
|
||||
if ((temp = name.indexOf (':')) >= 0) {
|
||||
name = name.substring (temp + 1);
|
||||
|
||||
// ... maybe that's enough (use/prefer default namespace) ...
|
||||
if (!isAttr && nsStack.processName (name, nsTemp, false) != null
|
||||
&& nsTemp [0].equals (ns)
|
||||
) {
|
||||
return nsTemp [2];
|
||||
}
|
||||
}
|
||||
|
||||
// must we define and use the default/undefined prefix?
|
||||
if ("".equals (ns)) {
|
||||
if (isAttr)
|
||||
fatalError ("processName bug");
|
||||
if (attributes.getIndex ("xmlns") != -1)
|
||||
fatalError ("need to undefine default NS, but it's bound: "
|
||||
+ attributes.getValue ("xmlns"));
|
||||
|
||||
nsStack.declarePrefix ("", "");
|
||||
attributes.addAttribute ("", "", "xmlns", "CDATA", "");
|
||||
return name;
|
||||
}
|
||||
|
||||
// is there at least one non-null prefix we can use?
|
||||
for (Enumeration e = nsStack.getDeclaredPrefixes ();
|
||||
e.hasMoreElements ();
|
||||
/* NOP */) {
|
||||
String prefix = (String) e.nextElement ();
|
||||
String uri = nsStack.getURI (prefix);
|
||||
|
||||
if (uri == null || !uri.equals (ns))
|
||||
continue;
|
||||
return prefix + ":" + name;
|
||||
}
|
||||
|
||||
// no such luck. create a prefix name, declare it, use it.
|
||||
for (temp = 0; temp >= 0; temp++) {
|
||||
String prefix = prefixRoot + temp;
|
||||
|
||||
if (nsStack.getURI (prefix) == null) {
|
||||
nsStack.declarePrefix (prefix, ns);
|
||||
attributes.addAttribute ("", "", "xmlns:" + prefix,
|
||||
"CDATA", ns);
|
||||
return prefix + ":" + name;
|
||||
}
|
||||
}
|
||||
fatalError ("too many prefixes genned");
|
||||
// NOTREACHED
|
||||
return null;
|
||||
}
|
||||
|
||||
public void startElement (
|
||||
String uri, String localName,
|
||||
String qName, Attributes atts
|
||||
) throws SAXException
|
||||
{
|
||||
if (!pushedContext)
|
||||
nsStack.pushContext ();
|
||||
pushedContext = false;
|
||||
|
||||
// make sure we have all NS declarations handy before we start
|
||||
int length = atts.getLength ();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
String aName = atts.getQName (i);
|
||||
|
||||
if (!aName.startsWith ("xmlns"))
|
||||
continue;
|
||||
|
||||
String prefix;
|
||||
|
||||
if ("xmlns".equals (aName))
|
||||
prefix = "";
|
||||
else if (aName.indexOf (':') == 5)
|
||||
prefix = aName.substring (6);
|
||||
else // "xmlnsfoo" etc.
|
||||
continue;
|
||||
startPrefixMapping (prefix, atts.getValue (i));
|
||||
}
|
||||
|
||||
// put namespace decls at the start of our regenned attlist
|
||||
attributes.clear ();
|
||||
for (Enumeration e = nsStack.getDeclaredPrefixes ();
|
||||
e.hasMoreElements ();
|
||||
/* NOP */) {
|
||||
String prefix = (String) e.nextElement ();
|
||||
|
||||
attributes.addAttribute ("", "",
|
||||
("".equals (prefix)
|
||||
? "xmlns"
|
||||
: "xmlns:" + prefix),
|
||||
"CDATA",
|
||||
nsStack.getURI (prefix));
|
||||
}
|
||||
|
||||
// name fixups: element, then attributes.
|
||||
// fixName may declare a new prefix or, for the element,
|
||||
// redeclare the default (if element name needs it).
|
||||
qName = fixName (uri, localName, qName, false);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
String aName = atts.getQName (i);
|
||||
String aNS = atts.getURI (i);
|
||||
String aLocal = atts.getLocalName (i);
|
||||
String aType = atts.getType (i);
|
||||
String aValue = atts.getValue (i);
|
||||
|
||||
if (aName.startsWith ("xmlns"))
|
||||
continue;
|
||||
aName = fixName (aNS, aLocal, aName, true);
|
||||
attributes.addAttribute (aNS, aLocal, aName, aType, aValue);
|
||||
}
|
||||
|
||||
elementStack.push (qName);
|
||||
|
||||
// pass event along, with cleaned-up names and decls.
|
||||
super.startElement (uri, localName, qName, attributes);
|
||||
}
|
||||
|
||||
public void endElement (String uri, String localName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
nsStack.popContext ();
|
||||
qName = (String) elementStack.pop ();
|
||||
super.endElement (uri, localName, qName);
|
||||
}
|
||||
|
||||
/**
|
||||
* This call is not passed to the next consumer in the chain.
|
||||
* Prefix declarations and scopes are only exposed in their
|
||||
* attribute form.
|
||||
*/
|
||||
public void endPrefixMapping (String prefix)
|
||||
throws SAXException
|
||||
{ }
|
||||
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
elementStack.removeAllElements ();
|
||||
nsStack.reset ();
|
||||
super.endDocument ();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,723 @@
|
||||
/* PipelineFactory.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.ext.*;
|
||||
|
||||
|
||||
/**
|
||||
* This provides static factory methods for creating simple event pipelines.
|
||||
* These pipelines are specified by strings, suitable for passing on
|
||||
* command lines or embedding in element attributes. For example, one way
|
||||
* to write a pipeline that restores namespace syntax, validates (stopping
|
||||
* the pipeline on validity errors) and then writes valid data to standard
|
||||
* output is this: <pre>
|
||||
* nsfix | validate | write ( stdout )</pre>
|
||||
*
|
||||
* <p> In this syntax, the tokens are always separated by whitespace, and each
|
||||
* stage of the pipeline may optionally have a parameter (which can be a
|
||||
* pipeline) in parentheses. Interior stages are called filters, and the
|
||||
* rightmost end of a pipeline is called a terminus.
|
||||
*
|
||||
* <p> Stages are usually implemented by a single class, which may not be
|
||||
* able to act as both a filter and a terminus; but any terminus can be
|
||||
* automatically turned into a filter, through use of a {@link TeeConsumer}.
|
||||
* The stage identifiers are either class names, or are one of the following
|
||||
* short identifiers built into this class. (Most of these identifiers are
|
||||
* no more than aliases for classes.) The built-in identifiers include:</p>
|
||||
|
||||
<table border="1" cellpadding="3" cellspacing="0">
|
||||
<tr bgcolor="#ccccff" class="TableHeadingColor">
|
||||
<th align="center" width="5%">Stage</th>
|
||||
<th align="center" width="9%">Parameter</th>
|
||||
<th align="center" width="1%">Terminus</th>
|
||||
<th align="center">Description</th>
|
||||
</tr>
|
||||
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="../dom/Consumer.html">dom</a></td>
|
||||
<td><em>none</em></td>
|
||||
<td> yes </td>
|
||||
<td align="left"> Applications code can access a DOM Document built
|
||||
from the input event stream. When used as a filter, this buffers
|
||||
data up to an <em>endDocument</em> call, and then uses a DOM parser
|
||||
to report everything that has been recorded (which can easily be
|
||||
less than what was reported to it). </td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="NSFilter.html">nsfix</a></td>
|
||||
<td><em>none</em></td>
|
||||
<td>no</td>
|
||||
<td align="left">This stage ensures that the XML element and attribute
|
||||
names in its output use namespace prefixes and declarations correctly.
|
||||
That is, so that they match the "Namespace plus LocalName" naming data
|
||||
with which each XML element and attribute is already associated. </td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="EventFilter.html">null</a></td>
|
||||
<td><em>none</em></td>
|
||||
<td>yes</td>
|
||||
<td align="left">This stage ignores all input event data.</td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="CallFilter.html">server</a></td>
|
||||
<td><em>required</em><br> server URL </td>
|
||||
<td>no</td>
|
||||
<td align="left">Sends its input as XML request to a remote server,
|
||||
normally a web application server using the HTTP or HTTPS protocols.
|
||||
The output of this stage is the parsed response from that server.</td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="TeeConsumer.html">tee</a></td>
|
||||
<td><em>required</em><br> first pipeline</td>
|
||||
<td>no</td>
|
||||
<td align="left">This sends its events down two paths; its parameter
|
||||
is a pipeline descriptor for the first path, and the second path
|
||||
is the output of this stage.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="ValidationConsumer.html">validate</a></td>
|
||||
<td><em>none</em></td>
|
||||
<td>yes</td>
|
||||
<td align="left">This checks for validity errors, and reports them
|
||||
through its error handler. The input must include declaration events
|
||||
and some lexical events. </td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="WellFormednessFilter.html">wf</a></td>
|
||||
<td><em>none</em></td>
|
||||
<td>yes</td>
|
||||
<td align="left"> This class provides some basic "well formedness"
|
||||
tests on the input event stream, and reports a fatal error if any
|
||||
of them fail. One example: start/end calls for elements must match.
|
||||
No SAX parser is permitted to produce malformed output, but other
|
||||
components can easily do so.</td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td>write</td>
|
||||
<td><em>required</em><br> "stdout", "stderr", or filename</td>
|
||||
<td>yes</td>
|
||||
<td align="left"> Writes its input to the specified output, as pretty
|
||||
printed XML text encoded using UTF-8. Input events must be well
|
||||
formed and "namespace fixed", else the output won't be XML (or possibly
|
||||
namespace) conformant. The symbolic names represent
|
||||
<em>System.out</em> and <em>System.err</em> respectively; names must
|
||||
correspond to files which don't yet exist.</td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td>xhtml</td>
|
||||
<td><em>required</em><br> "stdout", "stderr", or filename</td>
|
||||
<td>yes</td>
|
||||
<td align="left"> Like <em>write</em> (above), except that XHTML rules
|
||||
are followed. The XHTML 1.0 Transitional document type is declared,
|
||||
and only ASCII characters are written (for interoperability). Other
|
||||
characters are written as entity or character references; the text is
|
||||
pretty printed.</td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="XIncludeFilter.html">xinclude</a></td>
|
||||
<td><em>none</em></td>
|
||||
<td>no</td>
|
||||
<td align="left">This stage handles XInclude processing.
|
||||
This is like entity inclusion, except that the included content
|
||||
is declared in-line rather than in the DTD at the beginning of
|
||||
a document.
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top" align="center">
|
||||
<td><a href="XsltFilter.html">xslt</a></td>
|
||||
<td><em>required</em><br> XSLT stylesheet URI</td>
|
||||
<td>no</td>
|
||||
<td align="left">This stage handles XSLT transformation
|
||||
according to a stylesheet.
|
||||
The implementation of the transformation may not actually
|
||||
stream data, although if such an XSLT engine is in use
|
||||
then that can happen.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
* <p> Note that {@link EventFilter#bind} can automatically eliminate
|
||||
* some filters by setting SAX2 parser features appropriately. This means
|
||||
* that you can routinely put filters like "nsfix", "validate", or "wf" at the
|
||||
* front of a pipeline (for components that need inputs conditioned to match
|
||||
* that level of correctness), and know that it won't actually be used unless
|
||||
* it's absolutely necessary.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class PipelineFactory
|
||||
{
|
||||
/**
|
||||
* Creates a simple pipeline according to the description string passed in.
|
||||
*/
|
||||
public static EventConsumer createPipeline (String description)
|
||||
throws IOException
|
||||
{
|
||||
return createPipeline (description, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends an existing pipeline by prepending the filter pipeline to the
|
||||
* specified consumer. Some pipelines need more customization than can
|
||||
* be done through this simplified syntax. When they are set up with
|
||||
* direct API calls, use this method to merge more complex pipeline
|
||||
* segments with easily configured ones.
|
||||
*/
|
||||
public static EventConsumer createPipeline (
|
||||
String description,
|
||||
EventConsumer next
|
||||
) throws IOException
|
||||
{
|
||||
// tokens are (for now) what's separated by whitespace;
|
||||
// very easy to parse, but IDs never have spaces.
|
||||
|
||||
StringTokenizer tokenizer;
|
||||
String tokens [];
|
||||
|
||||
tokenizer = new StringTokenizer (description);
|
||||
tokens = new String [tokenizer.countTokens ()];
|
||||
for (int i = 0; i < tokens.length; i++)
|
||||
tokens [i] = tokenizer.nextToken ();
|
||||
|
||||
PipelineFactory factory = new PipelineFactory ();
|
||||
Pipeline pipeline = factory.parsePipeline (tokens, next);
|
||||
|
||||
return pipeline.createPipeline ();
|
||||
}
|
||||
|
||||
|
||||
private PipelineFactory () { /* NYET */ }
|
||||
|
||||
|
||||
/**
|
||||
* Extends an existing pipeline by prepending a pre-tokenized filter
|
||||
* pipeline to the specified consumer. Tokens are class names (or the
|
||||
* predefined aliases) left and right parenthesis, and the vertical bar.
|
||||
*/
|
||||
public static EventConsumer createPipeline (
|
||||
String tokens [],
|
||||
EventConsumer next
|
||||
) throws IOException
|
||||
{
|
||||
PipelineFactory factory = new PipelineFactory ();
|
||||
Pipeline pipeline = factory.parsePipeline (tokens, next);
|
||||
|
||||
return pipeline.createPipeline ();
|
||||
}
|
||||
|
||||
|
||||
private String tokens [];
|
||||
private int index;
|
||||
|
||||
private Pipeline parsePipeline (String toks [], EventConsumer next)
|
||||
{
|
||||
tokens = toks;
|
||||
index = 0;
|
||||
|
||||
Pipeline retval = parsePipeline (next);
|
||||
|
||||
if (index != toks.length)
|
||||
throw new ArrayIndexOutOfBoundsException (
|
||||
"extra token: " + tokens [index]);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// pipeline ::= stage | stage '|' pipeline
|
||||
private Pipeline parsePipeline (EventConsumer next)
|
||||
{
|
||||
Pipeline retval = new Pipeline (parseStage ());
|
||||
|
||||
// minimal pipelines: "stage" and "... | id"
|
||||
if (index > (tokens.length - 2)
|
||||
|| !"|".equals (tokens [index])
|
||||
) {
|
||||
retval.next = next;
|
||||
return retval;
|
||||
}
|
||||
index++;
|
||||
retval.rest = parsePipeline (next);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// stage ::= id | id '(' pipeline ')'
|
||||
private Stage parseStage ()
|
||||
{
|
||||
Stage retval = new Stage (tokens [index++]);
|
||||
|
||||
// minimal stages: "id" and "id ( id )"
|
||||
if (index > (tokens.length - 2)
|
||||
|| !"(".equals (tokens [index]) /*)*/
|
||||
)
|
||||
return retval;
|
||||
|
||||
index++;
|
||||
retval.param = parsePipeline (null);
|
||||
if (index >= tokens.length)
|
||||
throw new ArrayIndexOutOfBoundsException (
|
||||
"missing right paren");
|
||||
if (/*(*/ !")".equals (tokens [index++]))
|
||||
throw new ArrayIndexOutOfBoundsException (
|
||||
"required right paren, not: " + tokens [index - 1]);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// these classes obey the conventions for constructors, so they're
|
||||
// only built in to this table of shortnames
|
||||
//
|
||||
// - filter (one or two types of arglist)
|
||||
// * last constructor is 'next' element
|
||||
// * optional (first) string parameter
|
||||
//
|
||||
// - terminus (one or types of arglist)
|
||||
// * optional (only) string parameter
|
||||
//
|
||||
// terminus stages are transformed into filters if needed, by
|
||||
// creating a "tee". filter stages aren't turned to terminus
|
||||
// stages though; either eliminate such stages, or add some
|
||||
// terminus explicitly.
|
||||
//
|
||||
private static final String builtinStages [][] = {
|
||||
{ "dom", "gnu.xml.dom.Consumer" },
|
||||
{ "nsfix", "gnu.xml.pipeline.NSFilter" },
|
||||
{ "null", "gnu.xml.pipeline.EventFilter" },
|
||||
{ "server", "gnu.xml.pipeline.CallFilter" },
|
||||
{ "tee", "gnu.xml.pipeline.TeeConsumer" },
|
||||
{ "validate", "gnu.xml.pipeline.ValidationConsumer" },
|
||||
{ "wf", "gnu.xml.pipeline.WellFormednessFilter" },
|
||||
{ "xinclude", "gnu.xml.pipeline.XIncludeFilter" },
|
||||
{ "xslt", "gnu.xml.pipeline.XsltFilter" },
|
||||
|
||||
// XXX want: option for validate, to preload external part of a DTD
|
||||
|
||||
// xhtml, write ... nyet generic-ready
|
||||
};
|
||||
|
||||
private static class Stage
|
||||
{
|
||||
String id;
|
||||
Pipeline param;
|
||||
|
||||
Stage (String name)
|
||||
{ id = name; }
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
if (param == null)
|
||||
return id;
|
||||
return id + " ( " + param + " )";
|
||||
}
|
||||
|
||||
private void fail (String message)
|
||||
throws IOException
|
||||
{
|
||||
throw new IOException ("in '" + id
|
||||
+ "' stage of pipeline, " + message);
|
||||
}
|
||||
|
||||
EventConsumer createStage (EventConsumer next)
|
||||
throws IOException
|
||||
{
|
||||
String name = id;
|
||||
|
||||
// most builtins are just class aliases
|
||||
for (int i = 0; i < builtinStages.length; i++) {
|
||||
if (id.equals (builtinStages [i][0])) {
|
||||
name = builtinStages [i][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Save output as XML or XHTML text
|
||||
if ("write".equals (name) || "xhtml".equals (name)) {
|
||||
String filename;
|
||||
boolean isXhtml = "xhtml".equals (name);
|
||||
OutputStream out = null;
|
||||
TextConsumer consumer;
|
||||
|
||||
if (param == null)
|
||||
fail ("parameter is required");
|
||||
|
||||
filename = param.toString ();
|
||||
if ("stdout".equals (filename))
|
||||
out = System.out;
|
||||
else if ("stderr".equals (filename))
|
||||
out = System.err;
|
||||
else {
|
||||
File f = new File (filename);
|
||||
|
||||
/*
|
||||
if (!f.isAbsolute ())
|
||||
fail ("require absolute file paths");
|
||||
*/
|
||||
if (f.exists ())
|
||||
fail ("file already exists: " + f.getName ());
|
||||
|
||||
// XXX this races against the existence test
|
||||
out = new FileOutputStream (f);
|
||||
}
|
||||
|
||||
if (!isXhtml)
|
||||
consumer = new TextConsumer (out);
|
||||
else
|
||||
consumer = new TextConsumer (
|
||||
new OutputStreamWriter (out, "8859_1"),
|
||||
true);
|
||||
|
||||
consumer.setPrettyPrinting (true);
|
||||
if (next == null)
|
||||
return consumer;
|
||||
return new TeeConsumer (consumer, next);
|
||||
|
||||
} else {
|
||||
//
|
||||
// Here go all the builtins that are just aliases for
|
||||
// classes, and all stage IDs that started out as such
|
||||
// class names. The following logic relies on several
|
||||
// documented conventions for constructor invocation.
|
||||
//
|
||||
String msg = null;
|
||||
|
||||
try {
|
||||
Class klass = Class.forName (name);
|
||||
Class argTypes [] = null;
|
||||
Constructor constructor = null;
|
||||
boolean filter = false;
|
||||
Object params [] = null;
|
||||
Object obj = null;
|
||||
|
||||
// do we need a filter stage?
|
||||
if (next != null) {
|
||||
// "next" consumer is always passed, with
|
||||
// or without the optional string param
|
||||
if (param == null) {
|
||||
argTypes = new Class [1];
|
||||
argTypes [0] = EventConsumer.class;
|
||||
|
||||
params = new Object [1];
|
||||
params [0] = next;
|
||||
|
||||
msg = "no-param filter";
|
||||
} else {
|
||||
argTypes = new Class [2];
|
||||
argTypes [0] = String.class;
|
||||
argTypes [1] = EventConsumer.class;
|
||||
|
||||
params = new Object [2];
|
||||
params [0] = param.toString ();
|
||||
params [1] = next;
|
||||
|
||||
msg = "one-param filter";
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
constructor = klass.getConstructor (argTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// try creating a filter from a
|
||||
// terminus and a tee
|
||||
filter = true;
|
||||
msg += " built from ";
|
||||
}
|
||||
}
|
||||
|
||||
// build from a terminus stage, with or
|
||||
// without the optional string param
|
||||
if (constructor == null) {
|
||||
String tmp;
|
||||
|
||||
if (param == null) {
|
||||
argTypes = new Class [0];
|
||||
params = new Object [0];
|
||||
|
||||
tmp = "no-param terminus";
|
||||
} else {
|
||||
argTypes = new Class [1];
|
||||
argTypes [0] = String.class;
|
||||
|
||||
params = new Object [1];
|
||||
params [0] = param.toString ();
|
||||
|
||||
tmp = "one-param terminus";
|
||||
}
|
||||
if (msg == null)
|
||||
msg = tmp;
|
||||
else
|
||||
msg += tmp;
|
||||
constructor = klass.getConstructor (argTypes);
|
||||
// NOT creating terminus by dead-ending
|
||||
// filters ... users should think about
|
||||
// that one, something's likely wrong
|
||||
}
|
||||
|
||||
obj = constructor.newInstance (params);
|
||||
|
||||
// return EventConsumers directly, perhaps after
|
||||
// turning them into a filter
|
||||
if (obj instanceof EventConsumer) {
|
||||
if (filter)
|
||||
return new TeeConsumer ((EventConsumer) obj, next);
|
||||
return (EventConsumer) obj;
|
||||
}
|
||||
|
||||
// if it's not a handler, it's an error
|
||||
// we can wrap handlers in a filter
|
||||
EventFilter retval = new EventFilter ();
|
||||
boolean updated = false;
|
||||
|
||||
if (obj instanceof ContentHandler) {
|
||||
retval.setContentHandler ((ContentHandler) obj);
|
||||
updated = true;
|
||||
}
|
||||
if (obj instanceof DTDHandler) {
|
||||
retval.setDTDHandler ((DTDHandler) obj);
|
||||
updated = true;
|
||||
}
|
||||
if (obj instanceof LexicalHandler) {
|
||||
retval.setProperty (
|
||||
EventFilter.PROPERTY_URI + "lexical-handler",
|
||||
obj);
|
||||
updated = true;
|
||||
}
|
||||
if (obj instanceof DeclHandler) {
|
||||
retval.setProperty (
|
||||
EventFilter.PROPERTY_URI + "declaration-handler",
|
||||
obj);
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (!updated)
|
||||
fail ("class is neither Consumer nor Handler");
|
||||
|
||||
if (filter)
|
||||
return new TeeConsumer (retval, next);
|
||||
return retval;
|
||||
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
fail (name + " constructor missing -- " + msg);
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
fail (name + " class not found");
|
||||
|
||||
} catch (Exception e) {
|
||||
// e.printStackTrace ();
|
||||
fail ("stage not available: " + e.getMessage ());
|
||||
}
|
||||
}
|
||||
// NOTREACHED
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Pipeline
|
||||
{
|
||||
Stage stage;
|
||||
|
||||
// rest may be null
|
||||
Pipeline rest;
|
||||
EventConsumer next;
|
||||
|
||||
Pipeline (Stage s)
|
||||
{ stage = s; }
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
if (rest == null && next == null)
|
||||
return stage.toString ();
|
||||
if (rest != null)
|
||||
return stage + " | " + rest;
|
||||
throw new IllegalArgumentException ("next");
|
||||
}
|
||||
|
||||
EventConsumer createPipeline ()
|
||||
throws IOException
|
||||
{
|
||||
if (next == null) {
|
||||
if (rest == null)
|
||||
next = stage.createStage (null);
|
||||
else
|
||||
next = stage.createStage (rest.createPipeline ());
|
||||
}
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public static void main (String argv [])
|
||||
{
|
||||
try {
|
||||
// three basic terminus cases
|
||||
createPipeline ("null");
|
||||
createPipeline ("validate");
|
||||
createPipeline ("write ( stdout )");
|
||||
|
||||
// four basic filters
|
||||
createPipeline ("nsfix | write ( stderr )");
|
||||
createPipeline ("wf | null");
|
||||
createPipeline ("null | null");
|
||||
createPipeline (
|
||||
"call ( http://www.example.com/services/xml-1a ) | xhtml ( stdout )");
|
||||
|
||||
// tee junctions
|
||||
createPipeline ("tee ( validate ) | write ( stdout )");
|
||||
createPipeline ("tee ( nsfix | write ( stdout ) ) | validate");
|
||||
|
||||
// longer pipeline
|
||||
createPipeline ("nsfix | tee ( validate ) | write ( stdout )");
|
||||
createPipeline (
|
||||
"null | wf | nsfix | tee ( validate ) | write ( stdout )");
|
||||
|
||||
// try some parsing error cases
|
||||
try {
|
||||
createPipeline ("null ("); // extra token '('
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
|
||||
try {
|
||||
createPipeline ("nsfix |"); // extra token '|'
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
|
||||
try {
|
||||
createPipeline ("xhtml ( foo"); // missing right paren
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
|
||||
try {
|
||||
createPipeline ("xhtml ( foo bar"); // required right paren
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
|
||||
try {
|
||||
createPipeline ("tee ( nsfix | validate");// missing right paren
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
|
||||
// try some construction error cases
|
||||
|
||||
try {
|
||||
createPipeline ("call"); // missing param
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("call ( foobar )"); // broken param
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("nsfix ( foobar )"); // illegal param
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("null ( foobar )"); // illegal param
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("wf ( foobar )"); // illegal param
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("xhtml ( foobar.html )");
|
||||
new File ("foobar.html").delete ();
|
||||
// now supported
|
||||
} catch (Exception e) {
|
||||
System.err.println ("** err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("xhtml"); // missing param
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("write ( stdout ) | null"); // nonterminal
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("validate | null");
|
||||
// now supported
|
||||
} catch (Exception e) {
|
||||
System.err.println ("** err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("validate ( foo )"); // illegal param
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
createPipeline ("tee"); // missing param
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
try {
|
||||
// only builtins so far
|
||||
createPipeline ("com.example.xml.FilterClass");
|
||||
System.err.println ("** didn't report error");
|
||||
} catch (Exception e) {
|
||||
System.err.println ("== err: " + e.getMessage ()); }
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace ();
|
||||
}
|
||||
}
|
||||
/**/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,413 @@
|
||||
/* TeeConsumer.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.ext.*;
|
||||
//import gnu.xml.util;
|
||||
|
||||
|
||||
/**
|
||||
* Fans its events out to two other consumers, a "tee" filter stage in an
|
||||
* event pipeline. Networks can be assembled with multiple output points.
|
||||
*
|
||||
* <p> Error handling should be simple if you remember that exceptions
|
||||
* you throw will cancel later stages in that callback's pipeline, and
|
||||
* generally the producer will stop if it sees such an exception. You
|
||||
* may want to protect your pipeline against such backflows, making a
|
||||
* kind of reverse filter (or valve?) so that certain exceptions thrown by
|
||||
* your pipeline will caught and handled before the producer sees them.
|
||||
* Just use a "try/catch" block, rememebering that really important
|
||||
* cleanup tasks should be in "finally" clauses.
|
||||
*
|
||||
* <p> That issue isn't unique to "tee" consumers, but tee consumers have
|
||||
* the additional twist that exceptions thrown by the first consumer
|
||||
* will cause the second consumer not to see the callback (except for
|
||||
* the endDocument callback, which signals state cleanup).
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
final public class TeeConsumer
|
||||
implements EventConsumer,
|
||||
ContentHandler, DTDHandler,
|
||||
LexicalHandler,DeclHandler
|
||||
{
|
||||
private EventConsumer first, rest;
|
||||
|
||||
// cached to minimize time overhead
|
||||
private ContentHandler docFirst, docRest;
|
||||
private DeclHandler declFirst, declRest;
|
||||
private LexicalHandler lexFirst, lexRest;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a consumer which sends all its events to the first
|
||||
* consumer, and then the second one. If the first consumer throws
|
||||
* an exception, the second one will not see the event which
|
||||
* caused that exception to be reported.
|
||||
*
|
||||
* @param car The first consumer to get the events
|
||||
* @param cdr The second consumer to get the events
|
||||
*/
|
||||
public TeeConsumer (EventConsumer car, EventConsumer cdr)
|
||||
{
|
||||
if (car == null || cdr == null)
|
||||
throw new NullPointerException ();
|
||||
first = car;
|
||||
rest = cdr;
|
||||
|
||||
//
|
||||
// Cache the handlers.
|
||||
//
|
||||
docFirst = first.getContentHandler ();
|
||||
docRest = rest.getContentHandler ();
|
||||
// DTD handler isn't cached (rarely needed)
|
||||
|
||||
try {
|
||||
declFirst = null;
|
||||
declFirst = (DeclHandler) first.getProperty (
|
||||
EventFilter.DECL_HANDLER);
|
||||
} catch (SAXException e) {}
|
||||
try {
|
||||
declRest = null;
|
||||
declRest = (DeclHandler) rest.getProperty (
|
||||
EventFilter.DECL_HANDLER);
|
||||
} catch (SAXException e) {}
|
||||
|
||||
try {
|
||||
lexFirst = null;
|
||||
lexFirst = (LexicalHandler) first.getProperty (
|
||||
EventFilter.LEXICAL_HANDLER);
|
||||
} catch (SAXException e) {}
|
||||
try {
|
||||
lexRest = null;
|
||||
lexRest = (LexicalHandler) rest.getProperty (
|
||||
EventFilter.LEXICAL_HANDLER);
|
||||
} catch (SAXException e) {}
|
||||
}
|
||||
|
||||
/* FIXME
|
||||
/**
|
||||
* Constructs a pipeline, and is otherwise a shorthand for the
|
||||
* two-consumer constructor for this class.
|
||||
*
|
||||
* @param first Description of the first pipeline to get events,
|
||||
* which will be passed to {@link PipelineFactory#createPipeline}
|
||||
* @param rest The second pipeline to get the events
|
||||
* /
|
||||
// constructor used by PipelineFactory
|
||||
public TeeConsumer (String first, EventConsumer rest)
|
||||
throws IOException
|
||||
{
|
||||
this (PipelineFactory.createPipeline (first), rest);
|
||||
}
|
||||
*/
|
||||
|
||||
/** Returns the first pipeline to get event calls. */
|
||||
public EventConsumer getFirst ()
|
||||
{ return first; }
|
||||
|
||||
/** Returns the second pipeline to get event calls. */
|
||||
public EventConsumer getRest ()
|
||||
{ return rest; }
|
||||
|
||||
/** Returns the content handler being used. */
|
||||
final public ContentHandler getContentHandler ()
|
||||
{
|
||||
if (docRest == null)
|
||||
return docFirst;
|
||||
if (docFirst == null)
|
||||
return docRest;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns the dtd handler being used. */
|
||||
final public DTDHandler getDTDHandler ()
|
||||
{
|
||||
// not cached (hardly used)
|
||||
if (rest.getDTDHandler () == null)
|
||||
return first.getDTDHandler ();
|
||||
if (first.getDTDHandler () == null)
|
||||
return rest.getDTDHandler ();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns the declaration or lexical handler being used. */
|
||||
final public Object getProperty (String id)
|
||||
throws SAXNotRecognizedException
|
||||
{
|
||||
//
|
||||
// in degenerate cases, we have no work to do.
|
||||
//
|
||||
Object firstProp = null, restProp = null;
|
||||
|
||||
try { firstProp = first.getProperty (id); }
|
||||
catch (SAXNotRecognizedException e) { /* ignore */ }
|
||||
try { restProp = rest.getProperty (id); }
|
||||
catch (SAXNotRecognizedException e) { /* ignore */ }
|
||||
|
||||
if (restProp == null)
|
||||
return firstProp;
|
||||
if (firstProp == null)
|
||||
return restProp;
|
||||
|
||||
//
|
||||
// we've got work to do; handle two builtin cases.
|
||||
//
|
||||
if (EventFilter.DECL_HANDLER.equals (id))
|
||||
return this;
|
||||
if (EventFilter.LEXICAL_HANDLER.equals (id))
|
||||
return this;
|
||||
|
||||
//
|
||||
// non-degenerate, handled by both consumers, but we don't know
|
||||
// how to handle this.
|
||||
//
|
||||
throw new SAXNotRecognizedException ("can't tee: " + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the error handler to both subsequent nodes of
|
||||
* this filter stage.
|
||||
*/
|
||||
public void setErrorHandler (ErrorHandler handler)
|
||||
{
|
||||
first.setErrorHandler (handler);
|
||||
rest.setErrorHandler (handler);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ContentHandler
|
||||
//
|
||||
public void setDocumentLocator (Locator locator)
|
||||
{
|
||||
// this call is not made by all parsers
|
||||
docFirst.setDocumentLocator (locator);
|
||||
docRest.setDocumentLocator (locator);
|
||||
}
|
||||
|
||||
public void startDocument ()
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.startDocument ();
|
||||
docRest.startDocument ();
|
||||
}
|
||||
|
||||
public void endDocument ()
|
||||
throws SAXException
|
||||
{
|
||||
try {
|
||||
docFirst.endDocument ();
|
||||
} finally {
|
||||
docRest.endDocument ();
|
||||
}
|
||||
}
|
||||
|
||||
public void startPrefixMapping (String prefix, String uri)
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.startPrefixMapping (prefix, uri);
|
||||
docRest.startPrefixMapping (prefix, uri);
|
||||
}
|
||||
|
||||
public void endPrefixMapping (String prefix)
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.endPrefixMapping (prefix);
|
||||
docRest.endPrefixMapping (prefix);
|
||||
}
|
||||
|
||||
public void skippedEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.skippedEntity (name);
|
||||
docRest.skippedEntity (name);
|
||||
}
|
||||
|
||||
public void startElement (String uri, String localName,
|
||||
String qName, Attributes atts)
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.startElement (uri, localName, qName, atts);
|
||||
docRest.startElement (uri, localName, qName, atts);
|
||||
}
|
||||
|
||||
public void endElement (String uri, String localName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.endElement (uri, localName, qName);
|
||||
docRest.endElement (uri, localName, qName);
|
||||
}
|
||||
|
||||
public void processingInstruction (String target, String data)
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.processingInstruction (target, data);
|
||||
docRest.processingInstruction (target, data);
|
||||
}
|
||||
|
||||
public void characters (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.characters (ch, start, length);
|
||||
docRest.characters (ch, start, length);
|
||||
}
|
||||
|
||||
public void ignorableWhitespace (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
docFirst.ignorableWhitespace (ch, start, length);
|
||||
docRest.ignorableWhitespace (ch, start, length);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DTDHandler
|
||||
//
|
||||
public void notationDecl (String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
DTDHandler l1 = first.getDTDHandler ();
|
||||
DTDHandler l2 = rest.getDTDHandler ();
|
||||
|
||||
l1.notationDecl (name, publicId, systemId);
|
||||
l2.notationDecl (name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void unparsedEntityDecl (String name,
|
||||
String publicId, String systemId,
|
||||
String notationName
|
||||
) throws SAXException
|
||||
{
|
||||
DTDHandler l1 = first.getDTDHandler ();
|
||||
DTDHandler l2 = rest.getDTDHandler ();
|
||||
|
||||
l1.unparsedEntityDecl (name, publicId, systemId, notationName);
|
||||
l2.unparsedEntityDecl (name, publicId, systemId, notationName);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DeclHandler
|
||||
//
|
||||
public void attributeDecl (String eName, String aName,
|
||||
String type,
|
||||
String mode, String value)
|
||||
throws SAXException
|
||||
{
|
||||
declFirst.attributeDecl (eName, aName, type, mode, value);
|
||||
declRest.attributeDecl (eName, aName, type, mode, value);
|
||||
}
|
||||
|
||||
public void elementDecl (String name, String model)
|
||||
throws SAXException
|
||||
{
|
||||
declFirst.elementDecl (name, model);
|
||||
declRest.elementDecl (name, model);
|
||||
}
|
||||
|
||||
public void externalEntityDecl (String name,
|
||||
String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
declFirst.externalEntityDecl (name, publicId, systemId);
|
||||
declRest.externalEntityDecl (name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void internalEntityDecl (String name, String value)
|
||||
throws SAXException
|
||||
{
|
||||
declFirst.internalEntityDecl (name, value);
|
||||
declRest.internalEntityDecl (name, value);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LexicalHandler
|
||||
//
|
||||
public void comment (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
lexFirst.comment (ch, start, length);
|
||||
lexRest.comment (ch, start, length);
|
||||
}
|
||||
|
||||
public void startCDATA ()
|
||||
throws SAXException
|
||||
{
|
||||
lexFirst.startCDATA ();
|
||||
lexRest.startCDATA ();
|
||||
}
|
||||
|
||||
public void endCDATA ()
|
||||
throws SAXException
|
||||
{
|
||||
lexFirst.endCDATA ();
|
||||
lexRest.endCDATA ();
|
||||
}
|
||||
|
||||
public void startEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
lexFirst.startEntity (name);
|
||||
lexRest.startEntity (name);
|
||||
}
|
||||
|
||||
public void endEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
lexFirst.endEntity (name);
|
||||
lexRest.endEntity (name);
|
||||
}
|
||||
|
||||
public void startDTD (String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
lexFirst.startDTD (name, publicId, systemId);
|
||||
lexRest.startDTD (name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void endDTD ()
|
||||
throws SAXException
|
||||
{
|
||||
lexFirst.endDTD ();
|
||||
lexRest.endDTD ();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/* TextConsumer.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import org.xml.sax.*;
|
||||
|
||||
import gnu.xml.util.XMLWriter;
|
||||
|
||||
|
||||
/**
|
||||
* Terminates a pipeline, consuming events to print them as well formed
|
||||
* XML (or XHTML) text.
|
||||
*
|
||||
* <p> Input must be well formed, and must include XML names (e.g. the
|
||||
* prefixes and prefix declarations must be present), or the output of
|
||||
* this class is undefined.
|
||||
*
|
||||
* @see NSFilter
|
||||
* @see WellFormednessFilter
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class TextConsumer extends XMLWriter implements EventConsumer
|
||||
{
|
||||
/**
|
||||
* Constructs an event consumer which echoes its input as text,
|
||||
* optionally adhering to some basic XHTML formatting options
|
||||
* which increase interoperability with old (v3) browsers.
|
||||
*
|
||||
* <p> For the best interoperability, when writing as XHTML only
|
||||
* ASCII characters are emitted; other characters are turned to
|
||||
* entity or character references as needed, and no XML declaration
|
||||
* is provided in the document.
|
||||
*/
|
||||
public TextConsumer (Writer w, boolean isXhtml)
|
||||
throws IOException
|
||||
{
|
||||
super (w, isXhtml ? "US-ASCII" : null);
|
||||
setXhtml (isXhtml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a consumer that writes its input as XML text.
|
||||
* XHTML rules are not followed.
|
||||
*/
|
||||
public TextConsumer (Writer w)
|
||||
throws IOException
|
||||
{
|
||||
this (w, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a consumer that writes its input as XML text,
|
||||
* encoded in UTF-8. XHTML rules are not followed.
|
||||
*/
|
||||
public TextConsumer (OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
this (new OutputStreamWriter (out, "UTF8"), false);
|
||||
}
|
||||
|
||||
/** <b>EventConsumer</b> Returns the document handler being used. */
|
||||
public ContentHandler getContentHandler ()
|
||||
{ return this; }
|
||||
|
||||
/** <b>EventConsumer</b> Returns the dtd handler being used. */
|
||||
public DTDHandler getDTDHandler ()
|
||||
{ return this; }
|
||||
|
||||
/** <b>XMLReader</b>Retrieves a property (lexical and decl handlers) */
|
||||
public Object getProperty (String propertyId)
|
||||
throws SAXNotRecognizedException
|
||||
{
|
||||
if (EventFilter.LEXICAL_HANDLER.equals (propertyId))
|
||||
return this;
|
||||
if (EventFilter.DECL_HANDLER.equals (propertyId))
|
||||
return this;
|
||||
throw new SAXNotRecognizedException (propertyId);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,362 @@
|
||||
/* WellFormednessFilter.java --
|
||||
Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.Stack;
|
||||
|
||||
import gnu.xml.aelfred2.SAXDriver;
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.ext.*;
|
||||
|
||||
|
||||
/**
|
||||
* This filter reports fatal exceptions in the case of event streams that
|
||||
* are not well formed. The rules currently tested include: <ul>
|
||||
*
|
||||
* <li>setDocumentLocator ... may be called only before startDocument
|
||||
*
|
||||
* <li>startDocument/endDocument ... must be paired, and all other
|
||||
* calls (except setDocumentLocator) must be nested within these.
|
||||
*
|
||||
* <li>startElement/endElement ... must be correctly paired, and
|
||||
* may never appear within CDATA sections.
|
||||
*
|
||||
* <li>comment ... can't contain "--"
|
||||
*
|
||||
* <li>character data ... can't contain "]]>"
|
||||
*
|
||||
* <li>whitespace ... can't contain CR
|
||||
*
|
||||
* <li>whitespace and character data must be within an element
|
||||
*
|
||||
* <li>processing instruction ... can't contain "?>" or CR
|
||||
*
|
||||
* <li>startCDATA/endCDATA ... must be correctly paired.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> Other checks for event stream correctness may be provided in
|
||||
* the future. For example, insisting that
|
||||
* entity boundaries nest correctly,
|
||||
* namespace scopes nest correctly,
|
||||
* namespace values never contain relative URIs,
|
||||
* attributes don't have "<" characters;
|
||||
* and more.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public final class WellFormednessFilter extends EventFilter
|
||||
{
|
||||
private boolean startedDoc;
|
||||
private Stack elementStack = new Stack ();
|
||||
private boolean startedCDATA;
|
||||
private String dtdState = "before";
|
||||
|
||||
|
||||
/**
|
||||
* Swallows all events after performing well formedness checks.
|
||||
*/
|
||||
// constructor used by PipelineFactory
|
||||
public WellFormednessFilter ()
|
||||
{ this (null); }
|
||||
|
||||
|
||||
/**
|
||||
* Passes events through to the specified consumer, after first
|
||||
* processing them.
|
||||
*/
|
||||
// constructor used by PipelineFactory
|
||||
public WellFormednessFilter (EventConsumer consumer)
|
||||
{
|
||||
super (consumer);
|
||||
|
||||
setContentHandler (this);
|
||||
setDTDHandler (this);
|
||||
|
||||
try {
|
||||
setProperty (LEXICAL_HANDLER, this);
|
||||
} catch (SAXException e) { /* can't happen */ }
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets state as if any preceding event stream was well formed.
|
||||
* Particularly useful if it ended through some sort of error,
|
||||
* and the endDocument call wasn't made.
|
||||
*/
|
||||
public void reset ()
|
||||
{
|
||||
startedDoc = false;
|
||||
startedCDATA = false;
|
||||
elementStack.removeAllElements ();
|
||||
}
|
||||
|
||||
|
||||
private SAXParseException getException (String message)
|
||||
{
|
||||
SAXParseException e;
|
||||
Locator locator = getDocumentLocator ();
|
||||
|
||||
if (locator == null)
|
||||
return new SAXParseException (message, null, null, -1, -1);
|
||||
else
|
||||
return new SAXParseException (message, locator);
|
||||
}
|
||||
|
||||
private void fatalError (String message)
|
||||
throws SAXException
|
||||
{
|
||||
SAXParseException e = getException (message);
|
||||
ErrorHandler handler = getErrorHandler ();
|
||||
|
||||
if (handler != null)
|
||||
handler.fatalError (e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception when called after startDocument.
|
||||
*
|
||||
* @param locator the locator, to be used in error reporting or relative
|
||||
* URI resolution.
|
||||
*
|
||||
* @exception IllegalStateException when called after the document
|
||||
* has already been started
|
||||
*/
|
||||
public void setDocumentLocator (Locator locator)
|
||||
{
|
||||
if (startedDoc)
|
||||
throw new IllegalStateException (
|
||||
"setDocumentLocator called after startDocument");
|
||||
super.setDocumentLocator (locator);
|
||||
}
|
||||
|
||||
public void startDocument () throws SAXException
|
||||
{
|
||||
if (startedDoc)
|
||||
fatalError ("startDocument called more than once");
|
||||
startedDoc = true;
|
||||
startedCDATA = false;
|
||||
elementStack.removeAllElements ();
|
||||
super.startDocument ();
|
||||
}
|
||||
|
||||
public void startElement (
|
||||
String uri, String localName,
|
||||
String qName, Attributes atts
|
||||
) throws SAXException
|
||||
{
|
||||
if (!startedDoc)
|
||||
fatalError ("callback outside of document?");
|
||||
if ("inside".equals (dtdState))
|
||||
fatalError ("element inside DTD?");
|
||||
else
|
||||
dtdState = "after";
|
||||
if (startedCDATA)
|
||||
fatalError ("element inside CDATA section");
|
||||
if (qName == null || "".equals (qName))
|
||||
fatalError ("startElement name missing");
|
||||
elementStack.push (qName);
|
||||
super.startElement (uri, localName, qName, atts);
|
||||
}
|
||||
|
||||
public void endElement (String uri, String localName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
if (!startedDoc)
|
||||
fatalError ("callback outside of document?");
|
||||
if (startedCDATA)
|
||||
fatalError ("element inside CDATA section");
|
||||
if (qName == null || "".equals (qName))
|
||||
fatalError ("endElement name missing");
|
||||
|
||||
try {
|
||||
String top = (String) elementStack.pop ();
|
||||
|
||||
if (!qName.equals (top))
|
||||
fatalError ("<" + top + " ...>...</" + qName + ">");
|
||||
// XXX could record/test namespace info
|
||||
} catch (EmptyStackException e) {
|
||||
fatalError ("endElement without startElement: </" + qName + ">");
|
||||
}
|
||||
super.endElement (uri, localName, qName);
|
||||
}
|
||||
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
if (!startedDoc)
|
||||
fatalError ("callback outside of document?");
|
||||
dtdState = "before";
|
||||
startedDoc = false;
|
||||
super.endDocument ();
|
||||
}
|
||||
|
||||
|
||||
public void startDTD (String root, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (!startedDoc)
|
||||
fatalError ("callback outside of document?");
|
||||
if ("before" != dtdState)
|
||||
fatalError ("two DTDs?");
|
||||
if (!elementStack.empty ())
|
||||
fatalError ("DTD must precede root element");
|
||||
dtdState = "inside";
|
||||
super.startDTD (root, publicId, systemId);
|
||||
}
|
||||
|
||||
public void notationDecl (String name, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
// FIXME: not all parsers will report startDTD() ...
|
||||
// we'd rather insist we're "inside".
|
||||
if ("after" == dtdState)
|
||||
fatalError ("not inside DTD");
|
||||
super.notationDecl (name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void unparsedEntityDecl (String name,
|
||||
String publicId, String systemId, String notationName)
|
||||
throws SAXException
|
||||
{
|
||||
// FIXME: not all parsers will report startDTD() ...
|
||||
// we'd rather insist we're "inside".
|
||||
if ("after" == dtdState)
|
||||
fatalError ("not inside DTD");
|
||||
super.unparsedEntityDecl (name, publicId, systemId, notationName);
|
||||
}
|
||||
|
||||
// FIXME: add the four DeclHandler calls too
|
||||
|
||||
public void endDTD ()
|
||||
throws SAXException
|
||||
{
|
||||
if (!startedDoc)
|
||||
fatalError ("callback outside of document?");
|
||||
if ("inside" != dtdState)
|
||||
fatalError ("DTD ends without start?");
|
||||
dtdState = "after";
|
||||
super.endDTD ();
|
||||
}
|
||||
|
||||
public void characters (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
int here = start, end = start + length;
|
||||
if (elementStack.empty ())
|
||||
fatalError ("characters must be in an element");
|
||||
while (here < end) {
|
||||
if (ch [here++] != ']')
|
||||
continue;
|
||||
if (here == end) // potential problem ...
|
||||
continue;
|
||||
if (ch [here++] != ']')
|
||||
continue;
|
||||
if (here == end) // potential problem ...
|
||||
continue;
|
||||
if (ch [here++] == '>')
|
||||
fatalError ("character data can't contain \"]]>\"");
|
||||
}
|
||||
super.characters (ch, start, length);
|
||||
}
|
||||
|
||||
public void ignorableWhitespace (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
int here = start, end = start + length;
|
||||
if (elementStack.empty ())
|
||||
fatalError ("characters must be in an element");
|
||||
while (here < end) {
|
||||
if (ch [here++] == '\r')
|
||||
fatalError ("whitespace can't contain CR");
|
||||
}
|
||||
super.ignorableWhitespace (ch, start, length);
|
||||
}
|
||||
|
||||
public void processingInstruction (String target, String data)
|
||||
throws SAXException
|
||||
{
|
||||
if (data.indexOf ('\r') > 0)
|
||||
fatalError ("PIs can't contain CR");
|
||||
if (data.indexOf ("?>") > 0)
|
||||
fatalError ("PIs can't contain \"?>\"");
|
||||
}
|
||||
|
||||
public void comment (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
if (!startedDoc)
|
||||
fatalError ("callback outside of document?");
|
||||
if (startedCDATA)
|
||||
fatalError ("comments can't nest in CDATA");
|
||||
int here = start, end = start + length;
|
||||
while (here < end) {
|
||||
if (ch [here] == '\r')
|
||||
fatalError ("comments can't contain CR");
|
||||
if (ch [here++] != '-')
|
||||
continue;
|
||||
if (here == end)
|
||||
fatalError ("comments can't end with \"--->\"");
|
||||
if (ch [here++] == '-')
|
||||
fatalError ("comments can't contain \"--\"");
|
||||
}
|
||||
super.comment (ch, start, length);
|
||||
}
|
||||
|
||||
public void startCDATA ()
|
||||
throws SAXException
|
||||
{
|
||||
if (!startedDoc)
|
||||
fatalError ("callback outside of document?");
|
||||
if (startedCDATA)
|
||||
fatalError ("CDATA starts can't nest");
|
||||
startedCDATA = true;
|
||||
super.startCDATA ();
|
||||
}
|
||||
|
||||
public void endCDATA ()
|
||||
throws SAXException
|
||||
{
|
||||
if (!startedDoc)
|
||||
fatalError ("callback outside of document?");
|
||||
if (!startedCDATA)
|
||||
fatalError ("CDATA end without start?");
|
||||
startedCDATA = false;
|
||||
super.endCDATA ();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,580 @@
|
||||
/* XIncludeFilter.java --
|
||||
Copyright (C) 2001,2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Stack;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import gnu.xml.util.Resolver;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Filter to process an XPointer-free subset of
|
||||
* <a href="http://www.w3.org/TR/xinclude">XInclude</a>, supporting its
|
||||
* use as a kind of replacement for parsed general entities.
|
||||
* XInclude works much like the <code>#include</code> of C/C++ but
|
||||
* works for XML documents as well as unparsed text files.
|
||||
* Restrictions from the 17-Sept-2002 CR draft of XInclude are as follows:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li> URIs must not include fragment identifiers.
|
||||
* The CR specifies support for XPointer <em>element()</em> fragment IDs,
|
||||
* which is not currently implemented here.
|
||||
*
|
||||
* <li> <em>xi:fallback</em> handling of resource errors is not
|
||||
* currently supported.
|
||||
*
|
||||
* <li> DTDs are not supported in included files, since the SAX DTD events
|
||||
* must have completely preceded any included file.
|
||||
* The CR explicitly allows the DTD related portions of the infoset to
|
||||
* grow as an effect of including XML documents.
|
||||
*
|
||||
* <li> <em>xml:base</em> fixup isn't done.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> XML documents that are included will normally be processed using
|
||||
* the default SAX namespace rules, meaning that prefix information may
|
||||
* be discarded. This may be changed with {@link #setSavingPrefixes
|
||||
* setSavingPrefixes()}. <em>You are strongly advised to do this.</em>
|
||||
*
|
||||
* <p> Note that XInclude allows highly incompatible implementations, which
|
||||
* are specialized to handle application-specific infoset extensions. Some
|
||||
* such implementations can be implemented by subclassing this one, but
|
||||
* they may only be substituted in applications at "user option".
|
||||
*
|
||||
* <p>TBD: "IURI" handling.
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
public class XIncludeFilter extends EventFilter implements Locator
|
||||
{
|
||||
private Hashtable extEntities = new Hashtable (5, 5);
|
||||
private int ignoreCount;
|
||||
private Stack uris = new Stack ();
|
||||
private Locator locator;
|
||||
private Vector inclusions = new Vector (5, 5);
|
||||
private boolean savingPrefixes;
|
||||
|
||||
/**
|
||||
*/
|
||||
public XIncludeFilter (EventConsumer next)
|
||||
throws SAXException
|
||||
{
|
||||
super (next);
|
||||
setContentHandler (this);
|
||||
// DTDHandler callbacks pass straight through
|
||||
setProperty (DECL_HANDLER, this);
|
||||
setProperty (LEXICAL_HANDLER, this);
|
||||
}
|
||||
|
||||
private void fatal (SAXParseException e) throws SAXException
|
||||
{
|
||||
ErrorHandler eh;
|
||||
|
||||
eh = getErrorHandler ();
|
||||
if (eh != null)
|
||||
eh.fatalError (e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes "this" down the filter chain as a proxy locator.
|
||||
*/
|
||||
public void setDocumentLocator (Locator locator)
|
||||
{
|
||||
this.locator = locator;
|
||||
super.setDocumentLocator (this);
|
||||
}
|
||||
|
||||
/** Used for proxy locator; do not call directly. */
|
||||
public String getSystemId ()
|
||||
{ return (locator == null) ? null : locator.getSystemId (); }
|
||||
/** Used for proxy locator; do not call directly. */
|
||||
public String getPublicId ()
|
||||
{ return (locator == null) ? null : locator.getPublicId (); }
|
||||
/** Used for proxy locator; do not call directly. */
|
||||
public int getLineNumber ()
|
||||
{ return (locator == null) ? -1 : locator.getLineNumber (); }
|
||||
/** Used for proxy locator; do not call directly. */
|
||||
public int getColumnNumber ()
|
||||
{ return (locator == null) ? -1 : locator.getColumnNumber (); }
|
||||
|
||||
/**
|
||||
* Assigns the flag controlling the setting of the SAX2
|
||||
* <em>namespace-prefixes</em> flag.
|
||||
*/
|
||||
public void setSavingPrefixes (boolean flag)
|
||||
{ savingPrefixes = flag; }
|
||||
|
||||
/**
|
||||
* Returns the flag controlling the setting of the SAX2
|
||||
* <em>namespace-prefixes</em> flag when parsing included documents.
|
||||
* The default value is the SAX2 default (false), which discards
|
||||
* information that can be useful.
|
||||
*/
|
||||
public boolean isSavingPrefixes ()
|
||||
{ return savingPrefixes; }
|
||||
|
||||
//
|
||||
// Two mechanisms are interacting here.
|
||||
//
|
||||
// - XML Base implies a stack of base URIs, updated both by
|
||||
// "real entity" boundaries and element boundaries.
|
||||
//
|
||||
// - Active "Real Entities" (for document and general entities,
|
||||
// and by xincluded files) are tracked to prevent circular
|
||||
// inclusions.
|
||||
//
|
||||
private String addMarker (String uri)
|
||||
throws SAXException
|
||||
{
|
||||
if (locator != null && locator.getSystemId () != null)
|
||||
uri = locator.getSystemId ();
|
||||
|
||||
// guard against InputSource objects without system IDs
|
||||
if (uri == null)
|
||||
fatal (new SAXParseException ("Entity URI is unknown", locator));
|
||||
|
||||
try {
|
||||
URL url = new URL (uri);
|
||||
|
||||
uri = url.toString ();
|
||||
if (inclusions.contains (uri))
|
||||
fatal (new SAXParseException (
|
||||
"XInclude, circular inclusion", locator));
|
||||
inclusions.addElement (uri);
|
||||
uris.push (url);
|
||||
} catch (IOException e) {
|
||||
// guard against illegal relative URIs (Xerces)
|
||||
fatal (new SAXParseException ("parser bug: relative URI",
|
||||
locator, e));
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
private void pop (String uri)
|
||||
{
|
||||
inclusions.removeElement (uri);
|
||||
uris.pop ();
|
||||
}
|
||||
|
||||
//
|
||||
// Document entity boundaries get both treatments.
|
||||
//
|
||||
public void startDocument () throws SAXException
|
||||
{
|
||||
ignoreCount = 0;
|
||||
addMarker (null);
|
||||
super.startDocument ();
|
||||
}
|
||||
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
inclusions.setSize (0);
|
||||
extEntities.clear ();
|
||||
uris.setSize (0);
|
||||
super.endDocument ();
|
||||
}
|
||||
|
||||
//
|
||||
// External general entity boundaries get both treatments.
|
||||
//
|
||||
public void externalEntityDecl (String name,
|
||||
String publicId, String systemId)
|
||||
throws SAXException
|
||||
{
|
||||
if (name.charAt (0) == '%')
|
||||
return;
|
||||
try {
|
||||
URL url = new URL (locator.getSystemId ());
|
||||
systemId = new URL (url, systemId).toString ();
|
||||
} catch (IOException e) {
|
||||
// what could we do?
|
||||
}
|
||||
extEntities.put (name, systemId);
|
||||
}
|
||||
|
||||
public void startEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount != 0) {
|
||||
ignoreCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
String uri = (String) extEntities.get (name);
|
||||
if (uri != null)
|
||||
addMarker (uri);
|
||||
super.startEntity (name);
|
||||
}
|
||||
|
||||
public void endEntity (String name)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount != 0) {
|
||||
if (--ignoreCount != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
String uri = (String) extEntities.get (name);
|
||||
|
||||
if (uri != null)
|
||||
pop (uri);
|
||||
super.endEntity (name);
|
||||
}
|
||||
|
||||
//
|
||||
// element boundaries only affect the base URI stack,
|
||||
// unless they're XInclude elements.
|
||||
//
|
||||
public void
|
||||
startElement (String uri, String localName, String qName, Attributes atts)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount != 0) {
|
||||
ignoreCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
URL baseURI = (URL) uris.peek ();
|
||||
String base;
|
||||
|
||||
base = atts.getValue ("http://www.w3.org/XML/1998/namespace", "base");
|
||||
if (base == null)
|
||||
uris.push (baseURI);
|
||||
else {
|
||||
URL url;
|
||||
|
||||
if (base.indexOf ('#') != -1)
|
||||
fatal (new SAXParseException (
|
||||
"xml:base with fragment: " + base,
|
||||
locator));
|
||||
|
||||
try {
|
||||
baseURI = new URL (baseURI, base);
|
||||
uris.push (baseURI);
|
||||
} catch (Exception e) {
|
||||
fatal (new SAXParseException (
|
||||
"xml:base with illegal uri: " + base,
|
||||
locator, e));
|
||||
}
|
||||
}
|
||||
|
||||
if (!"http://www.w3.org/2001/XInclude".equals (uri)) {
|
||||
super.startElement (uri, localName, qName, atts);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("include".equals (localName)) {
|
||||
String href = atts.getValue ("href");
|
||||
String parse = atts.getValue ("parse");
|
||||
String encoding = atts.getValue ("encoding");
|
||||
URL url = (URL) uris.peek ();
|
||||
SAXParseException x = null;
|
||||
|
||||
if (href == null)
|
||||
fatal (new SAXParseException (
|
||||
"XInclude missing href",
|
||||
locator));
|
||||
if (href.indexOf ('#') != -1)
|
||||
fatal (new SAXParseException (
|
||||
"XInclude with fragment: " + href,
|
||||
locator));
|
||||
|
||||
if (parse == null || "xml".equals (parse))
|
||||
x = xinclude (url, href);
|
||||
else if ("text".equals (parse))
|
||||
x = readText (url, href, encoding);
|
||||
else
|
||||
fatal (new SAXParseException (
|
||||
"unknown XInclude parsing mode: " + parse,
|
||||
locator));
|
||||
if (x == null) {
|
||||
// strip out all child content
|
||||
ignoreCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME the 17-Sept-2002 CR of XInclude says we "must"
|
||||
// use xi:fallback elements to handle resource errors,
|
||||
// if they exist.
|
||||
fatal (x);
|
||||
|
||||
} else if ("fallback".equals (localName)) {
|
||||
fatal (new SAXParseException (
|
||||
"illegal top level XInclude 'fallback' element",
|
||||
locator));
|
||||
} else {
|
||||
ErrorHandler eh = getErrorHandler ();
|
||||
|
||||
// CR doesn't say this is an error
|
||||
if (eh != null)
|
||||
eh.warning (new SAXParseException (
|
||||
"unrecognized toplevel XInclude element: " + localName,
|
||||
locator));
|
||||
super.startElement (uri, localName, qName, atts);
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement (String uri, String localName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount != 0) {
|
||||
if (--ignoreCount != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
uris.pop ();
|
||||
if (!("http://www.w3.org/2001/XInclude".equals (uri)
|
||||
&& "include".equals (localName)))
|
||||
super.endElement (uri, localName, qName);
|
||||
}
|
||||
|
||||
//
|
||||
// ignore all content within non-empty xi:include elements
|
||||
//
|
||||
public void characters (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.characters (ch, start, length);
|
||||
}
|
||||
|
||||
public void processingInstruction (String target, String value)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.processingInstruction (target, value);
|
||||
}
|
||||
|
||||
public void ignorableWhitespace (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.ignorableWhitespace (ch, start, length);
|
||||
}
|
||||
|
||||
public void comment (char ch [], int start, int length)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.comment (ch, start, length);
|
||||
}
|
||||
|
||||
public void startCDATA () throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.startCDATA ();
|
||||
}
|
||||
|
||||
public void endCDATA () throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.endCDATA ();
|
||||
}
|
||||
|
||||
public void startPrefixMapping (String prefix, String uri)
|
||||
throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.startPrefixMapping (prefix, uri);
|
||||
}
|
||||
|
||||
public void endPrefixMapping (String prefix) throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.endPrefixMapping (prefix);
|
||||
}
|
||||
|
||||
public void skippedEntity (String name) throws SAXException
|
||||
{
|
||||
if (ignoreCount == 0)
|
||||
super.skippedEntity (name);
|
||||
}
|
||||
|
||||
// JDK 1.1 seems to need it to be done this way, sigh
|
||||
void setLocator (Locator l) { locator = l; }
|
||||
Locator getLocator () { return locator; }
|
||||
|
||||
|
||||
//
|
||||
// for XIncluded entities, manage the current locator and
|
||||
// filter out events that would be incorrect to report
|
||||
//
|
||||
private class Scrubber extends EventFilter
|
||||
{
|
||||
Scrubber (EventFilter f)
|
||||
throws SAXException
|
||||
{
|
||||
// delegation passes to next in chain
|
||||
super (f);
|
||||
|
||||
// process all content events
|
||||
super.setContentHandler (this);
|
||||
super.setProperty (LEXICAL_HANDLER, this);
|
||||
|
||||
// drop all DTD events
|
||||
super.setDTDHandler (null);
|
||||
super.setProperty (DECL_HANDLER, null);
|
||||
}
|
||||
|
||||
// maintain proxy locator
|
||||
// only one startDocument()/endDocument() pair per event stream
|
||||
public void setDocumentLocator (Locator l)
|
||||
{ setLocator (l); }
|
||||
public void startDocument ()
|
||||
{ }
|
||||
public void endDocument ()
|
||||
{ }
|
||||
|
||||
private void reject (String message) throws SAXException
|
||||
{ fatal (new SAXParseException (message, getLocator ())); }
|
||||
|
||||
// only the DTD from the "base document" gets reported
|
||||
public void startDTD (String root, String publicId, String systemId)
|
||||
throws SAXException
|
||||
{ reject ("XIncluded DTD: " + systemId); }
|
||||
public void endDTD ()
|
||||
throws SAXException
|
||||
{ reject ("XIncluded DTD"); }
|
||||
// ... so this should never happen
|
||||
public void skippedEntity (String name) throws SAXException
|
||||
{ reject ("XInclude skipped entity: " + name); }
|
||||
|
||||
// since we rejected DTDs, only builtin entities can be reported
|
||||
}
|
||||
|
||||
// <xi:include parse='xml' ...>
|
||||
// relative to the base URI passed
|
||||
private SAXParseException xinclude (URL url, String href)
|
||||
throws SAXException
|
||||
{
|
||||
XMLReader helper;
|
||||
Scrubber scrubber;
|
||||
Locator savedLocator = locator;
|
||||
|
||||
// start with a parser acting just like our input
|
||||
// modulo DTD-ish stuff (validation flag, entity resolver)
|
||||
helper = XMLReaderFactory.createXMLReader ();
|
||||
helper.setErrorHandler (getErrorHandler ());
|
||||
helper.setFeature (FEATURE_URI + "namespace-prefixes", true);
|
||||
|
||||
// Set up the proxy locator and event filter.
|
||||
scrubber = new Scrubber (this);
|
||||
locator = null;
|
||||
bind (helper, scrubber);
|
||||
|
||||
// Merge the included document, except its DTD
|
||||
try {
|
||||
url = new URL (url, href);
|
||||
href = url.toString ();
|
||||
|
||||
if (inclusions.contains (href))
|
||||
fatal (new SAXParseException (
|
||||
"XInclude, circular inclusion", locator));
|
||||
|
||||
inclusions.addElement (href);
|
||||
uris.push (url);
|
||||
helper.parse (new InputSource (href));
|
||||
return null;
|
||||
} catch (java.io.IOException e) {
|
||||
return new SAXParseException (href, locator, e);
|
||||
} finally {
|
||||
pop (href);
|
||||
locator = savedLocator;
|
||||
}
|
||||
}
|
||||
|
||||
// <xi:include parse='text' ...>
|
||||
// relative to the base URI passed
|
||||
private SAXParseException readText (URL url, String href, String encoding)
|
||||
throws SAXException
|
||||
{
|
||||
InputStream in = null;
|
||||
|
||||
try {
|
||||
URLConnection conn;
|
||||
InputStreamReader reader;
|
||||
char buf [] = new char [4096];
|
||||
int count;
|
||||
|
||||
url = new URL (url, href);
|
||||
conn = url.openConnection ();
|
||||
in = conn.getInputStream ();
|
||||
if (encoding == null)
|
||||
encoding = Resolver.getEncoding (conn.getContentType ());
|
||||
if (encoding == null) {
|
||||
ErrorHandler eh = getErrorHandler ();
|
||||
if (eh != null)
|
||||
eh.warning (new SAXParseException (
|
||||
"guessing text encoding for URL: " + url,
|
||||
locator));
|
||||
reader = new InputStreamReader (in);
|
||||
} else
|
||||
reader = new InputStreamReader (in, encoding);
|
||||
|
||||
while ((count = reader.read (buf, 0, buf.length)) != -1)
|
||||
super.characters (buf, 0, count);
|
||||
in.close ();
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
return new SAXParseException (
|
||||
"can't XInclude text",
|
||||
locator, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/* XsltFilter.java --
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.pipeline;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.sax.*;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
|
||||
/**
|
||||
* Packages an XSLT transform as a pipeline component.
|
||||
* Note that all DTD events (callbacks to DeclHandler and DTDHandler
|
||||
* interfaces) are discarded, although XSLT transforms may be set up to
|
||||
* use the LexicalHandler to write DTDs with only an external subset.
|
||||
* Not every XSLT engine will necessarily be usable with this filter,
|
||||
* but current versions of
|
||||
* <a href="http://saxon.sourceforge.net">SAXON</a> and
|
||||
* <a href="http://xml.apache.org/xalan-j">Xalan</a> should work well.
|
||||
*
|
||||
* @see TransformerFactory
|
||||
*
|
||||
* @author David Brownell
|
||||
*/
|
||||
final public class XsltFilter extends EventFilter
|
||||
{
|
||||
/**
|
||||
* Creates a filter that performs the specified transform.
|
||||
* Uses the JAXP 1.1 interfaces to access the default XSLT
|
||||
* engine configured for in the current execution context,
|
||||
* and parses the stylesheet without custom EntityResolver
|
||||
* or ErrorHandler support.
|
||||
*
|
||||
* @param stylesheet URI for the stylesheet specifying the
|
||||
* XSLT transform
|
||||
* @param next provides the ContentHandler and LexicalHandler
|
||||
* to receive XSLT output.
|
||||
* @exception SAXException if the stylesheet can't be parsed
|
||||
* @exception IOException if there are difficulties
|
||||
* bootstrapping the XSLT engine, such as it not supporting
|
||||
* SAX well enough to use this way.
|
||||
*/
|
||||
public XsltFilter (String stylesheet, EventConsumer next)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
// First, get a transformer with the stylesheet preloaded
|
||||
TransformerFactory tf = null;
|
||||
TransformerHandler th;
|
||||
|
||||
try {
|
||||
SAXTransformerFactory stf;
|
||||
|
||||
tf = TransformerFactory.newInstance ();
|
||||
if (!tf.getFeature (SAXTransformerFactory.FEATURE) // sax inputs
|
||||
|| !tf.getFeature (SAXResult.FEATURE) // sax outputs
|
||||
|| !tf.getFeature (StreamSource.FEATURE) // stylesheet
|
||||
)
|
||||
throw new IOException ("XSLT factory ("
|
||||
+ tf.getClass ().getName ()
|
||||
+ ") does not support SAX");
|
||||
stf = (SAXTransformerFactory) tf;
|
||||
th = stf.newTransformerHandler (new StreamSource (stylesheet));
|
||||
} catch (TransformerConfigurationException e) {
|
||||
throw new IOException ("XSLT factory ("
|
||||
+ (tf == null
|
||||
? "none available"
|
||||
: tf.getClass ().getName ())
|
||||
+ ") configuration error, "
|
||||
+ e.getMessage ()
|
||||
);
|
||||
}
|
||||
|
||||
// Hook its outputs up to the pipeline ...
|
||||
SAXResult out = new SAXResult ();
|
||||
|
||||
out.setHandler (next.getContentHandler ());
|
||||
try {
|
||||
LexicalHandler lh;
|
||||
lh = (LexicalHandler) next.getProperty (LEXICAL_HANDLER);
|
||||
out.setLexicalHandler (lh);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
th.setResult (out);
|
||||
|
||||
// ... and make sure its inputs look like ours.
|
||||
setContentHandler (th);
|
||||
setProperty (LEXICAL_HANDLER, th);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
<html><head><title>
|
||||
blah
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 1999-2001 The Free Software Foundation, Inc.
|
||||
*/
|
||||
-->
|
||||
</title></head><body>
|
||||
|
||||
<p>This package exposes a kind of XML processing pipeline, based on sending
|
||||
SAX events, which can be used as components of application architectures.
|
||||
Pipelines are used to convey streams of processing events from a producer
|
||||
to one or more consumers, and to let each consumer control the data seen by
|
||||
later consumers.
|
||||
|
||||
<p> There is a <a href="PipelineFactory.html">PipelineFactory</a> class which
|
||||
accepts a syntax describing how to construct some simple pipelines. Strings
|
||||
describing such pipelines can be used in command line tools (see the
|
||||
<a href="../util/DoParse.html">DoParse</a> class)
|
||||
and in other places that it is
|
||||
useful to let processing be easily reconfigured. Pipelines can of course
|
||||
be constructed programmatically, providing access to options that the
|
||||
factory won't.
|
||||
|
||||
<p> Web applications are supported by making it easy for servlets (or
|
||||
non-Java web application components) to be part of a pipeline. They can
|
||||
originate XML (or XHTML) data through an <em>InputSource</em> or in
|
||||
response to XML messages sent from clients using <em>CallFilter</em>
|
||||
pipeline stages. Such facilities are available using the simple syntax
|
||||
for pipeline construction.
|
||||
|
||||
|
||||
<h2> Programming Models </h2>
|
||||
|
||||
<p> Pipelines should be simple to understand.
|
||||
|
||||
<ul>
|
||||
<li> XML content, typically entire documents,
|
||||
is pushed through consumers by producers.
|
||||
|
||||
<li> Pipelines are basically about consuming SAX2 callback events,
|
||||
where the events encapsulate XML infoset-level data.<ul>
|
||||
|
||||
<li> Pipelines are constructed by taking one or more consumer
|
||||
stages and combining them to produce a composite consumer.
|
||||
|
||||
<li> A pipeline is presumed to have pending tasks and state from
|
||||
the beginning of its ContentHandler.startDocument() callback until
|
||||
it's returned from its ContentHandler.doneDocument() callback.
|
||||
|
||||
<li> Pipelines may have multiple output stages ("fan-out")
|
||||
or multiple input stages ("fan-in") when appropriate.
|
||||
|
||||
<li> Pipelines may be long-lived, but need not be.
|
||||
|
||||
</ul>
|
||||
|
||||
<li> There is flexibility about event production. <ul>
|
||||
|
||||
<li> SAX2 XMLReader objects are producers, which
|
||||
provide a high level "pull" model: documents (text or DOM) are parsed,
|
||||
and the parser pushes individual events through the pipeline.
|
||||
|
||||
<li> Events can be pushed directly to event consumer components
|
||||
by application modules, if they invoke SAX2 callbacks directly.
|
||||
That is, application modules use the XML Infoset as exposed
|
||||
through SAX2 event callbacks.
|
||||
|
||||
</ul>
|
||||
|
||||
<li> Multiple producer threads may concurrently access a pipeline,
|
||||
if they coordinate appropriately.
|
||||
|
||||
<li> Pipeline processing is not the only framework applications
|
||||
will use.
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<h3> Producers: XMLReader or Custom </h3>
|
||||
|
||||
<p> Many producers will be SAX2 XMLReader objects, and
|
||||
will read (pull) data which is then written (pushed) as events.
|
||||
Typically these will parse XML text (acquired from
|
||||
<code>org.xml.sax.helpers.XMLReaderFactory</code>) or a DOM tree
|
||||
(using a <code><a href="../util/DomParser.html">DomParser</a></code>)
|
||||
These may be bound to event consumer using a convenience routine,
|
||||
<em><a href="EventFilter.html">EventFilter</a>.bind()</em>.
|
||||
Once bound, these producers may be given additional documents to
|
||||
sent through its pipeline.
|
||||
|
||||
<p> In other cases, you will write producers yourself. For example, some
|
||||
data structures might know how to write themselves out using one or
|
||||
more XML models, expressed as sequences of SAX2 event callbacks.
|
||||
An application module might
|
||||
itself be a producer, issuing startDocument and endDocument events
|
||||
and then asking those data structures to write themselves out to a
|
||||
given EventConsumer, or walking data structures (such as JDBC query
|
||||
results) and applying its own conversion rules. WAP format XML
|
||||
(WBMXL) can be directly converted to producer output.
|
||||
|
||||
<p> SAX2 introduced an "XMLFilter" interface, which is a kind of XMLReader.
|
||||
It is most useful in conjunction with its XMLFilterImpl helper class;
|
||||
see the <em><a href="EventFilter.html">EventFilter</a></em> javadoc
|
||||
for information contrasting that XMLFilterImpl approach with the
|
||||
relevant parts of this pipeline framework. Briefly, such XMLFilterImpl
|
||||
children can be either producers or consumers, and are more limited in
|
||||
configuration flexibility. In this framework, the focus of filters is
|
||||
on the EventConsumer side; see the section on
|
||||
<a href="#fitting">pipe fitting</a> below.
|
||||
|
||||
|
||||
<h3> Consume to Standard or Custom Data Representations </h3>
|
||||
|
||||
<p> Many consumers will be used to create standard representations of XML
|
||||
data. The <a href="TextConsumer.html">TextConsumer</a> takes its events
|
||||
and writes them as text for a single XML document,
|
||||
using an internal <a href="../util/XMLWriter.html">XMLWriter</a>.
|
||||
The <a href="DomConsumer.html">DomConsumer</a> takes its events and uses
|
||||
them to create and populate a DOM Document.
|
||||
|
||||
<p> In other cases, you will write consumers yourself. For example,
|
||||
you might use a particular unmarshaling filter to produce objects
|
||||
that fit your application's requirements, instead of using DOM.
|
||||
Such consumers work at the level of XML data models, rather than with
|
||||
specific representations such as XML text or a DOM tree. You could
|
||||
convert your output directly to WAP format data (WBXML).
|
||||
|
||||
|
||||
<h3><a name="fitting">Pipe Fitting</a></h3>
|
||||
|
||||
<p> Pipelines are composite event consumers, with each stage having
|
||||
the opportunity to transform the data before delivering it to any
|
||||
subsequent stages.
|
||||
|
||||
<p> The <a href="PipelineFactory.html">PipelineFactory</a> class
|
||||
provides access to much of this functionality through a simple syntax.
|
||||
See the table in that class's javadoc describing a number of standard
|
||||
components. Direct API calls are still needed for many of the most
|
||||
interesting pipeline configurations, including ones leveraging actual
|
||||
or logical concurrency.
|
||||
|
||||
<p> Four basic types of pipe fitting are directly supported. These may
|
||||
be used to construct complex pipeline networks. <ul>
|
||||
|
||||
<li> <a href="TeeConsumer.html">TeeConsumer</a> objects split event
|
||||
flow so it goes to two two different consumers, one before the other.
|
||||
This is a basic form of event fan-out; you can use this class to
|
||||
copy events to any number of output pipelines.
|
||||
|
||||
<li> Clients can call remote components through HTTP or HTTPS using
|
||||
the <a href="CallFilter.html">CallFilter</a> component, and Servlets
|
||||
can implement such components by extending the
|
||||
<a href="XmlServlet.html">XmlServlet</a> component. Java is not
|
||||
required on either end, and transport protocols other than HTTP may
|
||||
also be used.
|
||||
|
||||
<li> <a href="EventFilter.html">EventFilter</a> objects selectively
|
||||
provide handling for callbacks, and can pass unhandled ones to a
|
||||
subsequent stage. They are often subclassed, since much of the
|
||||
basic filtering machinery is already in place in the base class.
|
||||
|
||||
<li> Applications can merge two event flows by just using the same
|
||||
consumer in each one. If multiple threads are in use, synchronization
|
||||
needs to be addressed by the appropriate application level policy.
|
||||
|
||||
</ul>
|
||||
|
||||
<p> Note that filters can be as complex as
|
||||
<a href="XsltFilter.html">XSLT transforms</a>
|
||||
available) on input data, or as simple as removing simple syntax data
|
||||
such as ignorable whitespace, comments, and CDATA delimiters.
|
||||
Some simple "built-in" filters are part of this package.
|
||||
|
||||
|
||||
<h3> Coding Conventions: Filter and Terminus Stages</h3>
|
||||
|
||||
<p> If you follow these coding conventions, your classes may be used
|
||||
directly (give the full class name) in pipeline descriptions as understood
|
||||
by the PipelineFactory. There are four constructors the factory may
|
||||
try to use; in order of decreasing numbers of parameters, these are: <ul>
|
||||
|
||||
<li> Filters that need a single String setup parameter should have
|
||||
a public constructor with two parameters: that string, then the
|
||||
EventConsumer holding the "next" consumer to get events.
|
||||
|
||||
<li> Filters that don't need setup parameters should have a public
|
||||
constructor that accepts a single EventConsumer holding the "next"
|
||||
consumer to get events when they are done.
|
||||
|
||||
<li> Terminus stages may have a public constructor taking a single
|
||||
paramter: the string value of that parameter.
|
||||
|
||||
<li> Terminus stages may have a public no-parameters constructor.
|
||||
|
||||
</ul>
|
||||
|
||||
<p> Of course, classes may support more than one such usage convention;
|
||||
if they do, they can automatically be used in multiple modes. If you
|
||||
try to use a terminus class as a filter, and that terminus has a constructor
|
||||
with the appropriate number of arguments, it is automatically wrapped in
|
||||
a "tee" filter.
|
||||
|
||||
|
||||
<h2> Debugging Tip: "Tee" Joints can Snapshot Data</h2>
|
||||
|
||||
<p> It can sometimes be hard to see what's happening, when something
|
||||
goes wrong. Easily fixed: just snapshot the data. Then you can find
|
||||
out where things start to go wrong.
|
||||
|
||||
<p> If you're using pipeline descriptors so that they're easily
|
||||
administered, just stick a <em>write ( filename )</em>
|
||||
filter into the pipeline at an appropriate point.
|
||||
|
||||
<p> Inside your programs, you can do the same thing directly: perhaps
|
||||
by saving a Writer (perhaps a StringWriter) in a variable, using that
|
||||
to create a TextConsumer, and making that the first part of a tee --
|
||||
splicing that into your pipeline at a convenient location.
|
||||
|
||||
<p> You can also use a DomConsumer to buffer the data, but remember
|
||||
that DOM doesn't save all the information that XML provides, so that DOM
|
||||
snapshots are relatively low fidelity. They also are substantially more
|
||||
expensive in terms of memory than a StringWriter holding similar data.
|
||||
|
||||
<h2> Debugging Tip: Non-XML Producers</h2>
|
||||
|
||||
<p> Producers in pipelines don't need to start from XML
|
||||
data structures, such as text in XML syntax (likely coming
|
||||
from some <em>XMLReader</em> that parses XML) or a
|
||||
DOM representation (perhaps with a
|
||||
<a href="../util/DomParser.html">DomParser</a>).
|
||||
|
||||
<p> One common type of event producer will instead make
|
||||
direct calls to SAX event handlers returned from an
|
||||
<a href="EventConsumer.html">EventConsumer</a>.
|
||||
For example, making <em>ContentHandler.startElement</em>
|
||||
calls and matching <em>ContentHandler.endElement</em> calls.
|
||||
|
||||
<p> Applications making such calls can catch certain
|
||||
common "syntax errors" by using a
|
||||
<a href="WellFormednessFilter.html">WellFormednessFilter</a>.
|
||||
That filter will detect (and report) erroneous input data
|
||||
such as mismatched document, element, or CDATA start/end calls.
|
||||
Use such a filter near the head of the pipeline that your
|
||||
producer feeds, at least while debugging, to help ensure that
|
||||
you're providing legal XML Infoset data.
|
||||
|
||||
<p> You can also arrange to validate data on the fly.
|
||||
For DTD validation, you can configure a
|
||||
<a href="ValidationConsumer.html">ValidationConsumer</a>
|
||||
to work as a filter, using any DTD you choose.
|
||||
Other validation schemes can be handled with other
|
||||
validation filters.
|
||||
|
||||
</body></html>
|
||||
@@ -0,0 +1,321 @@
|
||||
/* AbstractNumberNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>number</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
abstract class AbstractNumberNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
static final int ALPHABETIC = 0;
|
||||
static final int TRADITIONAL = 1;
|
||||
|
||||
final TemplateNode format;
|
||||
final String lang;
|
||||
final int letterValue;
|
||||
final String groupingSeparator;
|
||||
final int groupingSize;
|
||||
|
||||
AbstractNumberNode(TemplateNode children, TemplateNode next,
|
||||
TemplateNode format, String lang,
|
||||
int letterValue, String groupingSeparator,
|
||||
int groupingSize)
|
||||
{
|
||||
super(children, next);
|
||||
this.format = format;
|
||||
this.lang = lang;
|
||||
this.letterValue = letterValue;
|
||||
this.groupingSeparator = groupingSeparator;
|
||||
this.groupingSize = groupingSize;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
format.apply(stylesheet, mode, context, pos, len, fragment, null);
|
||||
String f = Expr._string(context, Collections.singleton(fragment));
|
||||
String value = format(f, compute(stylesheet, context, pos, len));
|
||||
Text text = doc.createTextNode(value);
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(text, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(text);
|
||||
}
|
||||
// xsl:number doesn't process children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
String format(String format, int[] number)
|
||||
{
|
||||
if (number.length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
int start = 0, end = 0, len = format.length(); // region of format
|
||||
// Tokenize
|
||||
List tokens = new ArrayList((number.length * 2) + 1);
|
||||
List types = new ArrayList(tokens.size());
|
||||
while (end < len)
|
||||
{
|
||||
while (end < len && !isAlphanumeric(format.charAt(end)))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
if (end > start)
|
||||
{
|
||||
tokens.add(format.substring(start, end));
|
||||
types.add(Boolean.FALSE);
|
||||
}
|
||||
start = end;
|
||||
while (end < len && isAlphanumeric(format.charAt(end)))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
if (end > start)
|
||||
{
|
||||
tokens.add(format.substring(start, end));
|
||||
types.add(Boolean.TRUE);
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
// Process tokens
|
||||
StringBuffer buf = new StringBuffer();
|
||||
len = tokens.size();
|
||||
int pos = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
String token = (i < 0) ? "." : (String) tokens.get(i);
|
||||
boolean alpha = (i < 0) ? true :
|
||||
((Boolean) types.get(i)).booleanValue();
|
||||
if (!alpha)
|
||||
{
|
||||
buf.append(token);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos < number.length)
|
||||
{
|
||||
format(buf, number[pos++], token);
|
||||
if (((i + 1 == len) || (i + 2 == len)) &&
|
||||
(pos < number.length))
|
||||
{
|
||||
// More numbers than tokens, reuse last token
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
if (pos == number.length && i < (len - 2))
|
||||
{
|
||||
// No more numbers. Skip to the end...
|
||||
i = len - 2;
|
||||
if (((Boolean) types.get(i + 1)).booleanValue())
|
||||
{
|
||||
// number formatting token, ignore
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.err.println("format: '"+format+"' "+asList(number)+" = '"+buf.toString()+"'");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/*List asList(int[] number)
|
||||
{
|
||||
List l = new ArrayList();
|
||||
for (int i = 0; i < number.length; i++)
|
||||
l.add(new Integer(number[i]));
|
||||
return l;
|
||||
}*/
|
||||
|
||||
void format(StringBuffer buf, int number, String formatToken)
|
||||
{
|
||||
int len = formatToken.length();
|
||||
char c = formatToken.charAt(len - 1);
|
||||
if (Character.digit(c, 10) == 1)
|
||||
{
|
||||
// Check preceding characters
|
||||
for (int i = len - 2; i >= 0; i--)
|
||||
{
|
||||
if (formatToken.charAt(i) != (c - 1))
|
||||
{
|
||||
format(buf, number, "1");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Decimal representation
|
||||
String val = Integer.toString(number);
|
||||
for (int d = len - val.length(); d > 0; d--)
|
||||
{
|
||||
buf.append('0');
|
||||
}
|
||||
buf.append(val);
|
||||
}
|
||||
else if ("A".equals(formatToken))
|
||||
{
|
||||
buf.append(alphabetic('@', number));
|
||||
}
|
||||
else if ("a".equals(formatToken))
|
||||
{
|
||||
buf.append(alphabetic('`', number));
|
||||
}
|
||||
else if ("i".equals(formatToken))
|
||||
{
|
||||
buf.append(roman(false, number));
|
||||
}
|
||||
else if ("I".equals(formatToken))
|
||||
{
|
||||
buf.append(roman(true, number));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown numbering sequence
|
||||
format(buf, number, "1");
|
||||
}
|
||||
}
|
||||
|
||||
static final boolean isAlphanumeric(char c)
|
||||
{
|
||||
switch (Character.getType(c))
|
||||
{
|
||||
case Character.DECIMAL_DIGIT_NUMBER: // Nd
|
||||
case Character.LETTER_NUMBER: // Nl
|
||||
case Character.OTHER_NUMBER: // No
|
||||
case Character.UPPERCASE_LETTER: // Lu
|
||||
case Character.LOWERCASE_LETTER: // Ll
|
||||
case Character.TITLECASE_LETTER: // Lt
|
||||
case Character.MODIFIER_LETTER: // Lm
|
||||
case Character.OTHER_LETTER: // Lo
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static final String alphabetic(char offset, int number)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
while (number > 0)
|
||||
{
|
||||
int r = number % 26;
|
||||
number = number / 26;
|
||||
buf.insert(0, (char) (offset + r));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
static final int[] roman_numbers = {1, 5, 10, 50, 100, 500, 1000};
|
||||
static final char[] roman_chars = {'i', 'v', 'x', 'l', 'c', 'd', 'm'};
|
||||
|
||||
static final String roman(boolean upper, int number)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int pos = roman_numbers.length - 1; pos >= 0; pos -= 2)
|
||||
{
|
||||
int f = number / roman_numbers[pos];
|
||||
if (f != 0)
|
||||
{
|
||||
number = number % (f * roman_numbers[pos]);
|
||||
}
|
||||
if (f > 4 && f < 9)
|
||||
{
|
||||
buf.append(roman_chars[pos + 1]);
|
||||
f -= 5;
|
||||
}
|
||||
if (f == 4)
|
||||
{
|
||||
buf.append(roman_chars[pos]);
|
||||
buf.append(roman_chars[pos + 1]);
|
||||
}
|
||||
else if (f == 9)
|
||||
{
|
||||
buf.append(roman_chars[pos]);
|
||||
buf.append(roman_chars[pos + 2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; f > 0; f--)
|
||||
{
|
||||
buf.append(roman_chars[pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return upper ? buf.toString().toUpperCase() : buf.toString();
|
||||
}
|
||||
|
||||
abstract int[] compute(Stylesheet stylesheet, Node context, int pos, int len)
|
||||
throws TransformerException;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("format=");
|
||||
buf.append(format);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* ApplyImportsNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.text.DecimalFormat;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSLT <code>apply-imports</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ApplyImportsNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
ApplyImportsNode(TemplateNode children, TemplateNode next)
|
||||
{
|
||||
super(children, next);
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new ApplyImportsNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet));
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
TemplateNode t = stylesheet.getTemplate(mode, context, true);
|
||||
if (t != null)
|
||||
{
|
||||
t.apply(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/* ApplyTemplatesNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>apply-templates</code>
|
||||
* instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ApplyTemplatesNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr select;
|
||||
final QName mode;
|
||||
final List sortKeys;
|
||||
final List withParams;
|
||||
final boolean isDefault;
|
||||
|
||||
ApplyTemplatesNode(TemplateNode children, TemplateNode next,
|
||||
Expr select, QName mode,
|
||||
List sortKeys, List withParams, boolean isDefault)
|
||||
{
|
||||
super(children, next);
|
||||
this.select = select;
|
||||
this.mode = mode;
|
||||
this.sortKeys = sortKeys;
|
||||
this.withParams = withParams;
|
||||
this.isDefault = isDefault;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
int len = sortKeys.size();
|
||||
List sortKeys2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
|
||||
}
|
||||
len = withParams.size();
|
||||
List withParams2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
|
||||
}
|
||||
return new ApplyTemplatesNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
select.clone(stylesheet),
|
||||
mode, sortKeys2, withParams2, isDefault);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = select.evaluate(context, pos, len);
|
||||
if (ret != null && ret instanceof Collection)
|
||||
{
|
||||
if (withParams != null)
|
||||
{
|
||||
// push the parameter context
|
||||
stylesheet.bindings.push(false);
|
||||
// set the parameters
|
||||
for (Iterator i = withParams.iterator(); i.hasNext(); )
|
||||
{
|
||||
WithParam p = (WithParam) i.next();
|
||||
Object value = p.getValue(stylesheet, mode, context, pos, len);
|
||||
stylesheet.bindings.set(p.name, value, false);
|
||||
}
|
||||
}
|
||||
Collection ns = (Collection) ret;
|
||||
List nodes = new ArrayList(ns);
|
||||
if (sortKeys != null)
|
||||
{
|
||||
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
|
||||
{
|
||||
SortKey sortKey = (SortKey) i.next();
|
||||
sortKey.init(stylesheet, mode, context, pos, len, parent,
|
||||
nextSibling);
|
||||
}
|
||||
Collections.sort(nodes, new XSLComparator(sortKeys));
|
||||
}
|
||||
else
|
||||
{
|
||||
Collections.sort(nodes, documentOrderComparator);
|
||||
}
|
||||
int l = nodes.size();
|
||||
QName effectiveMode = isDefault ? mode : this.mode;
|
||||
for (int i = 0; i < l; i++)
|
||||
{
|
||||
Node node = (Node) nodes.get(i);
|
||||
TemplateNode t = stylesheet.getTemplate(effectiveMode, node,
|
||||
false);
|
||||
if (t != null)
|
||||
{
|
||||
if (stylesheet.debug)
|
||||
{
|
||||
System.err.println("Applying " + t);
|
||||
}
|
||||
stylesheet.current = node;
|
||||
t.apply(stylesheet, effectiveMode, node, i + 1, l,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
if (withParams != null)
|
||||
{
|
||||
// pop the variable context
|
||||
stylesheet.bindings.pop(false);
|
||||
}
|
||||
}
|
||||
// apply-templates doesn't have processable children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
boolean o = false;
|
||||
if (select != null)
|
||||
{
|
||||
buf.append("select=");
|
||||
buf.append(select);
|
||||
o = true;
|
||||
}
|
||||
if (mode != null)
|
||||
{
|
||||
if (o)
|
||||
{
|
||||
buf.append(',');
|
||||
}
|
||||
buf.append("mode=");
|
||||
buf.append(mode);
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
/* AttributeNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>attribute</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class AttributeNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final TemplateNode name;
|
||||
final TemplateNode namespace;
|
||||
final Node source;
|
||||
|
||||
AttributeNode(TemplateNode children, TemplateNode next, TemplateNode name,
|
||||
TemplateNode namespace, Node source)
|
||||
{
|
||||
super(children, next);
|
||||
this.name = name;
|
||||
this.namespace = namespace;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new AttributeNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null : next.clone(stylesheet),
|
||||
name.clone(stylesheet),
|
||||
(namespace == null) ? null :
|
||||
namespace.clone(stylesheet),
|
||||
source);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
// Create a document fragment to hold the name
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply name to the fragment
|
||||
name.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
String nameValue = Expr.stringValue(fragment);
|
||||
|
||||
String namespaceValue = null;
|
||||
if (namespace != null)
|
||||
{
|
||||
// Create a document fragment to hold the namespace
|
||||
fragment = doc.createDocumentFragment();
|
||||
// Apply namespace to the fragment
|
||||
namespace.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
namespaceValue = Expr.stringValue(fragment);
|
||||
if (namespaceValue.length() == 0)
|
||||
{
|
||||
namespaceValue = null;
|
||||
}
|
||||
}
|
||||
|
||||
String prefix = getPrefix(nameValue);
|
||||
if (namespaceValue == null)
|
||||
{
|
||||
if (prefix != null)
|
||||
{
|
||||
if (XMLConstants.XML_NS_PREFIX.equals(prefix))
|
||||
{
|
||||
namespaceValue = XMLConstants.XML_NS_URI;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Resolve namespace for this prefix
|
||||
namespaceValue = source.lookupNamespaceURI(prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prefix != null)
|
||||
{
|
||||
String ns2 = source.lookupNamespaceURI(prefix);
|
||||
if (ns2 != null && !ns2.equals(namespaceValue))
|
||||
{
|
||||
// prefix clashes, reset it
|
||||
prefix = null;
|
||||
int ci = nameValue.indexOf(':');
|
||||
nameValue = nameValue.substring(ci + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (prefix == null)
|
||||
{
|
||||
// Resolve prefix for this namespace
|
||||
prefix = source.lookupPrefix(namespaceValue);
|
||||
if (prefix != null)
|
||||
{
|
||||
nameValue = prefix + ":" + nameValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (namespaceValue != null)
|
||||
{
|
||||
// Must invent a prefix
|
||||
prefix = inventPrefix(parent);
|
||||
nameValue = prefix + ":" + nameValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
NamedNodeMap attrs = parent.getAttributes();
|
||||
boolean insert = true;
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceValue) ||
|
||||
XMLConstants.XMLNS_ATTRIBUTE.equals(nameValue) ||
|
||||
nameValue.startsWith("xmlns:"))
|
||||
{
|
||||
// Namespace declaration, do not output
|
||||
insert = false;
|
||||
}
|
||||
if (prefix != null && namespaceValue == null)
|
||||
{
|
||||
// Not a QName
|
||||
insert = false;
|
||||
}
|
||||
if (parent.getNodeType() == Node.ELEMENT_NODE &&
|
||||
parent.getFirstChild() != null)
|
||||
{
|
||||
// XSLT 7.1.3 Adding an attribute to an element after children have
|
||||
// been added to it is an error
|
||||
insert = false;
|
||||
}
|
||||
if (insert)
|
||||
{
|
||||
// Insert attribute
|
||||
Attr attr = (namespaceValue != null) ?
|
||||
doc.createAttributeNS(namespaceValue, nameValue) :
|
||||
doc.createAttribute(nameValue);
|
||||
if (attrs != null)
|
||||
{
|
||||
if (namespace != null)
|
||||
{
|
||||
attrs.setNamedItemNS(attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
attrs.setNamedItem(attr);
|
||||
}
|
||||
}
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
attr, null);
|
||||
}
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
final String getPrefix(String name)
|
||||
{
|
||||
int ci = name.indexOf(':');
|
||||
return (ci == -1) ? null : name.substring(0, ci);
|
||||
}
|
||||
|
||||
final String inventPrefix(Node parent)
|
||||
{
|
||||
String base = "ns";
|
||||
int count = 0;
|
||||
String ret = base + Integer.toString(count);
|
||||
while (parent.lookupNamespaceURI(ret) != null)
|
||||
{
|
||||
count++;
|
||||
ret = base + Integer.toString(count);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/* AttributeSet.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
/**
|
||||
* An attribute-set entry in a stylesheet.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class AttributeSet
|
||||
{
|
||||
|
||||
final TemplateNode children;
|
||||
final String name;
|
||||
final String uas;
|
||||
|
||||
AttributeSet(TemplateNode children, String name, String uas)
|
||||
{
|
||||
this.children = children;
|
||||
this.name = name;
|
||||
this.uas = uas;
|
||||
}
|
||||
|
||||
AttributeSet clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new AttributeSet((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
name, uas);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
/* Bindings.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPathVariableResolver;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* The set of variable bindings in effect for a stylesheet.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class Bindings
|
||||
implements XPathVariableResolver, Cloneable
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
|
||||
/**
|
||||
* Global variables.
|
||||
*/
|
||||
final LinkedList variables;
|
||||
|
||||
/**
|
||||
* Parameter value stack.
|
||||
*/
|
||||
final LinkedList parameters;
|
||||
|
||||
Bindings(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
variables = new LinkedList();
|
||||
parameters = new LinkedList();
|
||||
push(true);
|
||||
push(false);
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Bindings) super.clone();
|
||||
}
|
||||
catch (CloneNotSupportedException e)
|
||||
{
|
||||
throw new Error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void push(boolean global)
|
||||
{
|
||||
if (global)
|
||||
{
|
||||
variables.addFirst(new HashMap());
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters.addFirst(new HashMap());
|
||||
}
|
||||
}
|
||||
|
||||
void pop(boolean global)
|
||||
{
|
||||
if (global)
|
||||
{
|
||||
variables.removeFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(String name, boolean global)
|
||||
{
|
||||
Iterator i = global ? variables.iterator() : parameters.iterator();
|
||||
while (i.hasNext())
|
||||
{
|
||||
Map ctx = (Map) i.next();
|
||||
if (ctx.containsKey(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object get(String name, Node context, int pos, int len)
|
||||
{
|
||||
//System.err.println("bindings.get: "+name);
|
||||
//System.err.println("\t"+toString());
|
||||
Object ret = null;
|
||||
for (Iterator i = variables.iterator(); i.hasNext() && ret == null; )
|
||||
{
|
||||
Map vctx = (Map) i.next();
|
||||
ret = vctx.get(name);
|
||||
}
|
||||
if (ret == null)
|
||||
{
|
||||
for (Iterator i = parameters.iterator(); i.hasNext() && ret == null; )
|
||||
{
|
||||
Map pctx = (Map) i.next();
|
||||
ret = pctx.get(name);
|
||||
}
|
||||
}
|
||||
/*if (ret instanceof Expr && context != null)
|
||||
{
|
||||
Expr expr = (Expr) ret;
|
||||
ret = expr.evaluate(context, 1, 1);
|
||||
}*/
|
||||
if (ret instanceof Node)
|
||||
{
|
||||
ret = Collections.singleton(ret);
|
||||
}
|
||||
if (ret == null)
|
||||
{
|
||||
ret = "";
|
||||
}
|
||||
//System.err.println("\tret="+ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void set(String name, Object value, boolean global)
|
||||
{
|
||||
if (global)
|
||||
{
|
||||
Map context = (Map) variables.getFirst();
|
||||
context.put(name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Map context = (Map) parameters.getFirst();
|
||||
context.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Object resolveVariable(QName qName)
|
||||
{
|
||||
return get(qName.toString(), null, 1, 1);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
boolean next = false;
|
||||
Collection seen = new HashSet();
|
||||
buf.append('{');
|
||||
for (Iterator i = variables.iterator(); i.hasNext(); )
|
||||
{
|
||||
Map ctx = (Map) i.next();
|
||||
for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
buf.append(',');
|
||||
}
|
||||
else
|
||||
{
|
||||
next = true;
|
||||
}
|
||||
Map.Entry entry = (Map.Entry) j.next();
|
||||
Object key = entry.getKey();
|
||||
if (!seen.contains(key))
|
||||
{
|
||||
buf.append(key);
|
||||
buf.append('=');
|
||||
buf.append(entry.getValue());
|
||||
seen.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Iterator i = parameters.iterator(); i.hasNext(); )
|
||||
{
|
||||
Map ctx = (Map) i.next();
|
||||
for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
buf.append(',');
|
||||
}
|
||||
else
|
||||
{
|
||||
next = true;
|
||||
}
|
||||
Map.Entry entry = (Map.Entry) j.next();
|
||||
Object key = entry.getKey();
|
||||
if (!seen.contains(key))
|
||||
{
|
||||
buf.append(key);
|
||||
buf.append('=');
|
||||
buf.append(entry.getValue());
|
||||
seen.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.append('}');
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/* CallTemplateNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>call-template</code>
|
||||
* instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CallTemplateNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final QName name;
|
||||
final List withParams;
|
||||
|
||||
CallTemplateNode(TemplateNode children, TemplateNode next,
|
||||
QName name, List withParams)
|
||||
{
|
||||
super(children, next);
|
||||
this.name = name;
|
||||
this.withParams = withParams;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
int len = withParams.size();
|
||||
List withParams2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
|
||||
}
|
||||
return new CallTemplateNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
name, withParams2);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (withParams != null)
|
||||
{
|
||||
// push the parameter context
|
||||
stylesheet.bindings.push(false);
|
||||
// set the parameters
|
||||
for (Iterator i = withParams.iterator(); i.hasNext(); )
|
||||
{
|
||||
WithParam p = (WithParam) i.next();
|
||||
Object value = p.getValue(stylesheet, mode, context, pos, len);
|
||||
stylesheet.bindings.set(p.name, value, false);
|
||||
}
|
||||
}
|
||||
TemplateNode t = stylesheet.getTemplate(mode, name);
|
||||
if (t != null)
|
||||
{
|
||||
t.apply(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (withParams != null)
|
||||
{
|
||||
// pop the variable context
|
||||
stylesheet.bindings.pop(false);
|
||||
}
|
||||
// call-template doesn't have processable children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/* ChooseNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>choose</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ChooseNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
ChooseNode(TemplateNode children, TemplateNode next)
|
||||
{
|
||||
super(children, next);
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new ChooseNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet));
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/* CommentNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Comment;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>comment</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CommentNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
CommentNode(TemplateNode children, TemplateNode next)
|
||||
{
|
||||
super(children, next);
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new CommentNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet));
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
String value = "";
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
if (children != null)
|
||||
{
|
||||
// Create a document fragment to hold the text
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply children to the fragment
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
value = Expr.stringValue(fragment);
|
||||
}
|
||||
Comment comment = doc.createComment(value);
|
||||
// Insert into result tree
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(comment, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(comment);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/* CopyNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>copy</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CopyNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final String uas;
|
||||
|
||||
CopyNode(TemplateNode children, TemplateNode next, String uas)
|
||||
{
|
||||
super(children, next);
|
||||
this.uas = uas;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new CopyNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
uas);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Node copy = parent;
|
||||
switch (context.getNodeType())
|
||||
{
|
||||
case Node.TEXT_NODE:
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
case Node.ELEMENT_NODE:
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
case Node.COMMENT_NODE:
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
copy = context.cloneNode(false);
|
||||
copy = doc.adoptNode(copy);
|
||||
if (copy.getNodeType() == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
if (parent.getFirstChild() != null)
|
||||
{
|
||||
// Ignore attempt to add attribute after children
|
||||
}
|
||||
else
|
||||
{
|
||||
NamedNodeMap attrs = parent.getAttributes();
|
||||
if (attrs != null)
|
||||
{
|
||||
attrs.setNamedItemNS(copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(copy, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uas != null)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(uas, " ");
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
addAttributeSet(stylesheet, mode, context, pos, len,
|
||||
copy, null, st.nextToken());
|
||||
}
|
||||
}
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
copy, null);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
void addAttributeSet(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling, String attributeSet)
|
||||
throws TransformerException
|
||||
{
|
||||
for (Iterator i = stylesheet.attributeSets.iterator(); i.hasNext(); )
|
||||
{
|
||||
AttributeSet as = (AttributeSet) i.next();
|
||||
if (!as.name.equals(attributeSet))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (as.uas != null)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(as.uas, " ");
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
addAttributeSet(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling, st.nextToken());
|
||||
}
|
||||
}
|
||||
if (as.children != null)
|
||||
{
|
||||
as.children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/* CopyOfNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSLT <code>copy-of</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CopyOfNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr select;
|
||||
|
||||
CopyOfNode(TemplateNode children, TemplateNode next, Expr select)
|
||||
{
|
||||
super(children, next);
|
||||
this.select = select;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new CopyOfNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
select.clone(stylesheet));
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = select.evaluate(context, pos, len);
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
if (ret instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) ret;
|
||||
List list = new ArrayList(ns);
|
||||
Collections.sort(list, documentOrderComparator);
|
||||
for (Iterator i = list.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node src = (Node) i.next();
|
||||
short nodeType = src.getNodeType();
|
||||
if (nodeType == Node.DOCUMENT_NODE)
|
||||
{
|
||||
// Use document element
|
||||
src = ((Document) src).getDocumentElement();
|
||||
if (src == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
nodeType = Node.ELEMENT_NODE;
|
||||
}
|
||||
else if (nodeType == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
if (parent.getFirstChild() != null)
|
||||
{
|
||||
// Ignore attempt to add attribute after children
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (parent.getNodeType() == Node.ATTRIBUTE_NODE &&
|
||||
nodeType != Node.TEXT_NODE &&
|
||||
nodeType != Node.ENTITY_REFERENCE_NODE)
|
||||
{
|
||||
// Ignore
|
||||
continue;
|
||||
}
|
||||
Node node = src.cloneNode(true);
|
||||
node = doc.adoptNode(node);
|
||||
if (nodeType == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
NamedNodeMap attrs = parent.getAttributes();
|
||||
if (attrs != null)
|
||||
{
|
||||
attrs.setNamedItemNS(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(node, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String value = Expr._string(context, ret);
|
||||
if (value != null && value.length() > 0)
|
||||
{
|
||||
Text textNode = doc.createTextNode(value);
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(textNode, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(textNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
// copy-of doesn't process children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("select=");
|
||||
buf.append(select);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/* CurrentFunction.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>current()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CurrentFunction
|
||||
extends Expr
|
||||
implements Function, XPathFunction
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
|
||||
CurrentFunction(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// We can't do anything useful here.
|
||||
// So much for the JAXP API...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
return Collections.singleton(stylesheet.current);
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
Stylesheet s = stylesheet;
|
||||
if (context instanceof Stylesheet)
|
||||
{
|
||||
s = (Stylesheet) context;
|
||||
}
|
||||
return new CurrentFunction(s);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "current()";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/* DOMSourceLocator.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.transform.dom.DOMLocator;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Simple DOMLocator implementation.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DOMSourceLocator
|
||||
implements DOMLocator
|
||||
{
|
||||
|
||||
final Node node;
|
||||
|
||||
DOMSourceLocator(Node node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public Node getOriginatingNode()
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public String getPublicId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSystemId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getLineNumber()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getColumnNumber()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/* DocumentFunction.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.URIResolver;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Constant;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
import gnu.xml.xpath.IdFunction;
|
||||
|
||||
/**
|
||||
* The XSLT <code>document()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class DocumentFunction
|
||||
extends Expr
|
||||
implements Function, XPathFunction
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
final Node base;
|
||||
List args;
|
||||
List values;
|
||||
|
||||
DocumentFunction(Stylesheet stylesheet, Node base)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
values = args;
|
||||
return evaluate(null, 1, 1);
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
int arity = args.size();
|
||||
if (values == null)
|
||||
{
|
||||
values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
}
|
||||
Object ret;
|
||||
switch (arity)
|
||||
{
|
||||
case 1:
|
||||
Object arg = values.get(0);
|
||||
if (arg instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) arg;
|
||||
Collection acc = new TreeSet();
|
||||
for (Iterator i = ns.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node node = (Node) i.next();
|
||||
String s = Expr.stringValue(node);
|
||||
acc.addAll(document(s, node.getBaseURI()));
|
||||
}
|
||||
ret = acc;
|
||||
}
|
||||
else
|
||||
{
|
||||
String s = Expr._string(context, arg);
|
||||
ret = document(s, base.getBaseURI());
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
Object arg1 = values.get(0);
|
||||
Object arg2 = values.get(1);
|
||||
if (!(arg2 instanceof Collection))
|
||||
{
|
||||
throw new RuntimeException("second argument is not a node-set");
|
||||
}
|
||||
Collection arg2ns = (Collection) arg2;
|
||||
String base2 = arg2ns.isEmpty() ? null :
|
||||
((Node) arg2ns.iterator().next()).getBaseURI();
|
||||
if (arg1 instanceof Collection)
|
||||
{
|
||||
Collection arg1ns = (Collection) arg1;
|
||||
Collection acc = new TreeSet();
|
||||
for (Iterator i = arg1ns.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node node = (Node) i.next();
|
||||
String s = Expr.stringValue(node);
|
||||
acc.addAll(document(s, base2));
|
||||
}
|
||||
ret = acc;
|
||||
}
|
||||
else
|
||||
{
|
||||
String s = Expr._string(context, arg1);
|
||||
ret = document(s, base2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("invalid arity");
|
||||
}
|
||||
values = null;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* The XSL <code>document</code> function.
|
||||
* @see XSLT 12.1
|
||||
* @param uri the URI from which to retrieve nodes
|
||||
* @param base the base URI for relative URIs
|
||||
*/
|
||||
Collection document(String uri, String base)
|
||||
{
|
||||
if ("".equals(uri) || uri == null)
|
||||
{
|
||||
uri = this.base.getBaseURI();
|
||||
}
|
||||
|
||||
// Get fragment
|
||||
Expr fragment = null;
|
||||
int hi = uri.indexOf('#');
|
||||
if (hi != -1)
|
||||
{
|
||||
String f = uri.substring(hi + 1);
|
||||
uri = uri.substring(0, hi);
|
||||
// TODO handle xpointer() here
|
||||
// this only handles IDs
|
||||
fragment = new IdFunction(new Constant(f));
|
||||
}
|
||||
|
||||
// Get document source
|
||||
try
|
||||
{
|
||||
DOMSource source;
|
||||
XSLURIResolver resolver = stylesheet.factory.resolver;
|
||||
synchronized (resolver)
|
||||
{
|
||||
if (stylesheet.transformer != null)
|
||||
{
|
||||
resolver.setUserResolver(stylesheet.transformer.uriResolver);
|
||||
resolver.setUserListener(stylesheet.transformer.errorListener);
|
||||
}
|
||||
source = resolver.resolveDOM(null, base, uri);
|
||||
}
|
||||
Node node = source.getNode();
|
||||
if (fragment == null)
|
||||
{
|
||||
return Collections.singleton(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
Object ret = fragment.evaluate(node, 1, 1);
|
||||
if (!(ret instanceof Collection))
|
||||
{
|
||||
// XXX Report error?
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
return (Collection) ret;
|
||||
}
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
String msg = "can't open " + uri;
|
||||
if (base != null)
|
||||
{
|
||||
msg += " with base " + base;
|
||||
}
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
Stylesheet s = stylesheet;
|
||||
if (context instanceof Stylesheet)
|
||||
{
|
||||
s = (Stylesheet) context;
|
||||
}
|
||||
DocumentFunction f = new DocumentFunction(s, base);
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/* ElementAvailableFunction.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>element-available</code> function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class ElementAvailableFunction
|
||||
extends Expr
|
||||
implements Function, XPathFunction
|
||||
{
|
||||
|
||||
static final Collection elements;
|
||||
static
|
||||
{
|
||||
TreeSet acc = new TreeSet();
|
||||
acc.add("stylesheet");
|
||||
acc.add("template");
|
||||
acc.add("param");
|
||||
acc.add("variable");
|
||||
acc.add("include");
|
||||
acc.add("import");
|
||||
acc.add("output");
|
||||
acc.add("preserve-space");
|
||||
acc.add("strip-space");
|
||||
acc.add("key");
|
||||
acc.add("decimal-format");
|
||||
acc.add("namespace-alias");
|
||||
acc.add("attribute-set");
|
||||
acc.add("apply-templates");
|
||||
acc.add("call-template");
|
||||
acc.add("value-of");
|
||||
acc.add("for-each");
|
||||
acc.add("if");
|
||||
acc.add("choose");
|
||||
acc.add("when");
|
||||
acc.add("otherwise");
|
||||
acc.add("element");
|
||||
acc.add("attribute");
|
||||
acc.add("text");
|
||||
acc.add("copy");
|
||||
acc.add("processing-instruction");
|
||||
acc.add("comment");
|
||||
acc.add("number");
|
||||
acc.add("copy-of");
|
||||
acc.add("message");
|
||||
acc.add("sort");
|
||||
acc.add("with-param");
|
||||
acc.add("fallback");
|
||||
acc.add("apply-imports");
|
||||
elements = Collections.unmodifiableSet(acc);
|
||||
}
|
||||
|
||||
final NamespaceContext nsctx;
|
||||
List args;
|
||||
|
||||
ElementAvailableFunction(NamespaceContext nsctx)
|
||||
{
|
||||
this.nsctx = nsctx;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
Expr arg = (Expr) args.get(0);
|
||||
Object val = arg.evaluate(context, pos, len);
|
||||
String name = _string(context, val);
|
||||
String prefix, localName, uri;
|
||||
int ci = name.indexOf(':');
|
||||
if (ci == -1)
|
||||
{
|
||||
prefix = null;
|
||||
localName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = name.substring(0, ci);
|
||||
localName = name.substring(ci + 1);
|
||||
}
|
||||
uri = nsctx.getNamespaceURI(prefix);
|
||||
if (Stylesheet.XSL_NS.equals(uri))
|
||||
{
|
||||
return elements.contains(localName) ?
|
||||
Boolean.TRUE : Boolean.FALSE;
|
||||
// TODO extension elements
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
NamespaceContext n = nsctx;
|
||||
if (context instanceof NamespaceContext)
|
||||
{
|
||||
n = (NamespaceContext) context;
|
||||
}
|
||||
ElementAvailableFunction f = new ElementAvailableFunction(n);
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
/* ElementNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>element</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ElementNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final TemplateNode name;
|
||||
final TemplateNode namespace;
|
||||
final String uas;
|
||||
final Node source;
|
||||
final Collection elementExcludeResultPrefixes;
|
||||
|
||||
ElementNode(TemplateNode children, TemplateNode next, TemplateNode name,
|
||||
TemplateNode namespace, String uas, Node source)
|
||||
{
|
||||
super(children, next);
|
||||
this.name = name;
|
||||
this.namespace = namespace;
|
||||
this.uas = uas;
|
||||
this.source = source;
|
||||
NamedNodeMap attrs = source.getAttributes();
|
||||
Node attr = attrs.getNamedItemNS(Stylesheet.XSL_NS,
|
||||
"exclude-result-prefixes");
|
||||
if (attr != null)
|
||||
{
|
||||
elementExcludeResultPrefixes = new HashSet();
|
||||
StringTokenizer st = new StringTokenizer(attr.getNodeValue());
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
elementExcludeResultPrefixes.add(st.nextToken());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementExcludeResultPrefixes = Collections.EMPTY_SET;
|
||||
}
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new ElementNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
name.clone(stylesheet),
|
||||
(namespace == null) ? null :
|
||||
namespace.clone(stylesheet),
|
||||
uas, source);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
// Create a document fragment to hold the name
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply name to the fragment
|
||||
name.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
String nameValue = Expr.stringValue(fragment);
|
||||
|
||||
String namespaceValue = null;
|
||||
if (namespace != null)
|
||||
{
|
||||
// Create a document fragment to hold the namespace
|
||||
fragment = doc.createDocumentFragment();
|
||||
// Apply namespace to the fragment
|
||||
namespace.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
namespaceValue = Expr.stringValue(fragment);
|
||||
if (namespaceValue.length() == 0)
|
||||
{
|
||||
namespaceValue = null;
|
||||
}
|
||||
}
|
||||
|
||||
String prefix = getPrefix(nameValue);
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix))
|
||||
{
|
||||
int ci = nameValue.indexOf(':');
|
||||
nameValue = nameValue.substring(ci + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Namespace aliasing
|
||||
if (prefix == null)
|
||||
{
|
||||
prefix = "#default";
|
||||
}
|
||||
String resultPrefix =
|
||||
(String) stylesheet.namespaceAliases.get(prefix);
|
||||
if (resultPrefix != null)
|
||||
{
|
||||
if ("#default".equals(resultPrefix))
|
||||
{
|
||||
resultPrefix = null;
|
||||
}
|
||||
namespaceValue = source.lookupNamespaceURI(resultPrefix);
|
||||
}
|
||||
if (prefix == "#default")
|
||||
{
|
||||
prefix = null;
|
||||
}
|
||||
// Look up ordinary namespace for this prefix
|
||||
if (namespaceValue == null)
|
||||
{
|
||||
if (XMLConstants.XML_NS_PREFIX.equals(prefix))
|
||||
{
|
||||
namespaceValue = XMLConstants.XML_NS_URI;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Resolve namespace for this prefix
|
||||
namespaceValue = source.lookupNamespaceURI(prefix);
|
||||
}
|
||||
}
|
||||
/*if (prefix == null)
|
||||
{
|
||||
// Resolve prefix for this namespace
|
||||
prefix = parent.lookupPrefix(namespaceValue);
|
||||
if (prefix != null)
|
||||
{
|
||||
nameValue = prefix + ":" + nameValue;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
// Create element
|
||||
Element element = (namespaceValue != null) ?
|
||||
doc.createElementNS(namespaceValue, nameValue) :
|
||||
doc.createElement(nameValue);
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(element, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(element);
|
||||
}
|
||||
stylesheet.addNamespaceNodes(source, element, doc,
|
||||
elementExcludeResultPrefixes);
|
||||
if (uas != null)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(uas, " ");
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
addAttributeSet(stylesheet, mode, context, pos, len,
|
||||
element, null, st.nextToken());
|
||||
}
|
||||
}
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
element, null);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
final String getPrefix(String name)
|
||||
{
|
||||
int ci = name.indexOf(':');
|
||||
return (ci == -1) ? null : name.substring(0, ci);
|
||||
}
|
||||
|
||||
void addAttributeSet(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling, String attributeSet)
|
||||
throws TransformerException
|
||||
{
|
||||
for (Iterator i = stylesheet.attributeSets.iterator(); i.hasNext(); )
|
||||
{
|
||||
AttributeSet as = (AttributeSet) i.next();
|
||||
if (!as.name.equals(attributeSet))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (as.uas != null)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(as.uas, " ");
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
addAttributeSet(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling, st.nextToken());
|
||||
}
|
||||
}
|
||||
if (as.children != null)
|
||||
{
|
||||
as.children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
if (uas != null)
|
||||
{
|
||||
buf.append(",uas=");
|
||||
buf.append(uas);
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/* ErrorListenerErrorHandler.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* An ErrorHandler that wraps an ErrorListener.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class ErrorListenerErrorHandler
|
||||
implements ErrorHandler
|
||||
{
|
||||
|
||||
final ErrorListener listener;
|
||||
|
||||
ErrorListenerErrorHandler(ErrorListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void warning(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.warning(new TransformerException(e));
|
||||
}
|
||||
catch (TransformerException e2)
|
||||
{
|
||||
throw new SAXException(e2);
|
||||
}
|
||||
}
|
||||
|
||||
public void error(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.error(new TransformerException(e));
|
||||
}
|
||||
catch (TransformerException e2)
|
||||
{
|
||||
throw new SAXException(e2);
|
||||
}
|
||||
}
|
||||
|
||||
public void fatalError(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.fatalError(new TransformerException(e));
|
||||
}
|
||||
catch (TransformerException e2)
|
||||
{
|
||||
throw new SAXException(e2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/* ForEachNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSLT <code>for-each</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ForEachNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr select;
|
||||
final List sortKeys;
|
||||
|
||||
ForEachNode(TemplateNode children, TemplateNode next, Expr select,
|
||||
List sortKeys)
|
||||
{
|
||||
super(children, next);
|
||||
this.select = select;
|
||||
this.sortKeys = sortKeys;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
int len = sortKeys.size();
|
||||
List sortKeys2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
|
||||
}
|
||||
return new ForEachNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
select.clone(stylesheet),
|
||||
sortKeys2);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
// Set current template to null
|
||||
Template saved = stylesheet.currentTemplate;
|
||||
stylesheet.currentTemplate = null;
|
||||
Object ret = select.evaluate(context, pos, len);
|
||||
//System.err.println(toString() + ": " + context+" -> "+ret);
|
||||
if (ret instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) ret;
|
||||
List list = new ArrayList(ns);
|
||||
if (sortKeys != null)
|
||||
{
|
||||
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
|
||||
{
|
||||
SortKey sortKey = (SortKey) i.next();
|
||||
sortKey.init(stylesheet, mode, context, pos, len, parent,
|
||||
nextSibling);
|
||||
}
|
||||
Collections.sort(list, new XSLComparator(sortKeys));
|
||||
}
|
||||
else
|
||||
{
|
||||
Collections.sort(list, documentOrderComparator);
|
||||
}
|
||||
// Perform children for each node
|
||||
int l = list.size();
|
||||
int p = 1;
|
||||
for (Iterator i = list.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node node = (Node) i.next();
|
||||
stylesheet.current = node;
|
||||
children.apply(stylesheet, mode,
|
||||
node, p++, l,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
// Restore current template
|
||||
stylesheet.currentTemplate = saved;
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("select=");
|
||||
buf.append(select);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/* FormatNumberFunction.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>format-number()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class FormatNumberFunction
|
||||
extends Expr
|
||||
implements XPathFunction, Function
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
List args;
|
||||
|
||||
FormatNumberFunction(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
int arity = args.size();
|
||||
List values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
double number = _number(context, values.get(0));
|
||||
String pattern = _string(context, values.get(1));
|
||||
// Currency symbol ¤ is not supposed to be present
|
||||
if (pattern.indexOf('\u00a4') != -1)
|
||||
{
|
||||
// Replace with $ (Xalan does this)
|
||||
pattern = pattern.replace('\u00a4', '$');
|
||||
}
|
||||
String dfName = null;
|
||||
if (arity > 2)
|
||||
{
|
||||
dfName = _string(context, values.get(2));
|
||||
// otherwise the default decimal-format will be used
|
||||
}
|
||||
DecimalFormat df = (DecimalFormat) stylesheet.decimalFormats.get(dfName);
|
||||
if (df == null)
|
||||
{
|
||||
throw new IllegalArgumentException("No such decimal-format: " +
|
||||
dfName);
|
||||
}
|
||||
df.applyLocalizedPattern(pattern);
|
||||
return df.format(number);
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
Stylesheet s = stylesheet;
|
||||
if (context instanceof Stylesheet)
|
||||
{
|
||||
s = (Stylesheet) context;
|
||||
}
|
||||
FormatNumberFunction f = new FormatNumberFunction(s);
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/* FunctionAvailableFunction.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>function-available</code> function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class FunctionAvailableFunction
|
||||
extends Expr
|
||||
implements Function, XPathFunction
|
||||
{
|
||||
|
||||
static final Collection xsltFunctions;
|
||||
static final Collection xpathFunctions;
|
||||
static
|
||||
{
|
||||
TreeSet acc = new TreeSet();
|
||||
acc.add("document");
|
||||
acc.add("key");
|
||||
acc.add("format-number");
|
||||
acc.add("current");
|
||||
acc.add("unparsed-entity-uri");
|
||||
acc.add("generate-id");
|
||||
acc.add("system-property");
|
||||
acc.add("element-available");
|
||||
acc.add("function-available");
|
||||
xsltFunctions = Collections.unmodifiableSet(acc);
|
||||
acc = new TreeSet();
|
||||
acc.add("boolean");
|
||||
acc.add("ceiling");
|
||||
acc.add("concat");
|
||||
acc.add("contains");
|
||||
acc.add("count");
|
||||
acc.add("false");
|
||||
acc.add("floor");
|
||||
acc.add("id");
|
||||
acc.add("lang");
|
||||
acc.add("last");
|
||||
acc.add("local-name");
|
||||
acc.add("name");
|
||||
acc.add("namespace-uri");
|
||||
acc.add("normalize-space");
|
||||
acc.add("not");
|
||||
acc.add("number");
|
||||
acc.add("position");
|
||||
acc.add("round");
|
||||
acc.add("starts-with");
|
||||
acc.add("string");
|
||||
acc.add("string-length");
|
||||
acc.add("substring-after");
|
||||
acc.add("substring-before");
|
||||
acc.add("substring");
|
||||
acc.add("sum");
|
||||
acc.add("translate");
|
||||
acc.add("true");
|
||||
xpathFunctions = Collections.unmodifiableSet(acc);
|
||||
}
|
||||
|
||||
final NamespaceContext nsctx;
|
||||
List args;
|
||||
|
||||
FunctionAvailableFunction(NamespaceContext nsctx)
|
||||
{
|
||||
this.nsctx = nsctx;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
Expr arg = (Expr) args.get(0);
|
||||
Object val = arg.evaluate(context, pos, len);
|
||||
String name = _string(context, val);
|
||||
String prefix, localName, uri;
|
||||
int ci = name.indexOf(':');
|
||||
if (ci == -1)
|
||||
{
|
||||
prefix = null;
|
||||
localName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = name.substring(0, ci);
|
||||
localName = name.substring(ci + 1);
|
||||
}
|
||||
uri = nsctx.getNamespaceURI(prefix);
|
||||
if (uri == null)
|
||||
{
|
||||
return xsltFunctions.contains(localName) ||
|
||||
xpathFunctions.contains(localName) ?
|
||||
Boolean.TRUE : Boolean.FALSE;
|
||||
// TODO extension functions
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
NamespaceContext n = nsctx;
|
||||
if (context instanceof NamespaceContext)
|
||||
{
|
||||
n = (NamespaceContext) context;
|
||||
}
|
||||
FunctionAvailableFunction f = new FunctionAvailableFunction(n);
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/* GenerateIdFunction.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>generate-id()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class GenerateIdFunction
|
||||
extends Expr
|
||||
implements XPathFunction, Function
|
||||
{
|
||||
|
||||
List args;
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
int arity = args.size();
|
||||
List values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
Node node;
|
||||
Collection ns = (arity == 0) ? Collections.EMPTY_SET :
|
||||
(Collection) values.get(0);
|
||||
if (ns.isEmpty())
|
||||
{
|
||||
node = context;
|
||||
}
|
||||
else
|
||||
{
|
||||
List list = new ArrayList(ns);
|
||||
Collections.sort(list, documentOrderComparator);
|
||||
node = (Node) list.get(0);
|
||||
}
|
||||
|
||||
String name = node.getNodeName();
|
||||
int index = 0, depth = 0;
|
||||
for (Node ctx = node.getPreviousSibling(); ctx != null;
|
||||
ctx = ctx.getPreviousSibling())
|
||||
{
|
||||
index++;
|
||||
}
|
||||
for (Node ctx = node.getParentNode(); ctx != null;
|
||||
ctx = ctx.getParentNode())
|
||||
{
|
||||
depth++;
|
||||
}
|
||||
return name + "-" + index + "-" + depth;
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
GenerateIdFunction f = new GenerateIdFunction();
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/* IfNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>if</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class IfNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr test;
|
||||
|
||||
IfNode(TemplateNode children, TemplateNode next, Expr test)
|
||||
{
|
||||
super(children, next);
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new IfNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
test.clone(stylesheet));
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = test.evaluate(context, pos, len);
|
||||
boolean success = (ret instanceof Boolean) ?
|
||||
((Boolean) ret).booleanValue() :
|
||||
Expr._boolean(context, ret);
|
||||
if (success)
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("test=");
|
||||
buf.append(test);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/* Key.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Pattern;
|
||||
|
||||
/**
|
||||
* An XSL key.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class Key
|
||||
{
|
||||
|
||||
final QName name;
|
||||
final Pattern match;
|
||||
final Expr use;
|
||||
|
||||
Key(QName name, Pattern match, Expr use)
|
||||
{
|
||||
this.name = name;
|
||||
this.match = match;
|
||||
this.use = use;
|
||||
}
|
||||
|
||||
Key clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new Key(name,
|
||||
(Pattern) match.clone(stylesheet),
|
||||
use.clone(stylesheet));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/* KeyFunction.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
import gnu.xml.xpath.Pattern;
|
||||
|
||||
/**
|
||||
* The XSLT <code>key()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class KeyFunction
|
||||
extends Pattern
|
||||
implements XPathFunction, Function
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
List args;
|
||||
|
||||
KeyFunction(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public boolean matches(Node context)
|
||||
{
|
||||
Object ret = evaluate(context, 1, 1);
|
||||
return !((Collection) ret).isEmpty();
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
// Evaluate arguments
|
||||
int arity = args.size();
|
||||
List values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
// Get key name
|
||||
QName keyName = QName.valueOf(_string(context, values.get(0)));
|
||||
// Expand qualified name
|
||||
String uri = keyName.getNamespaceURI();
|
||||
String prefix = keyName.getPrefix();
|
||||
if ((uri == null || uri.length() == 0) &&
|
||||
(prefix != null && prefix.length() > 0))
|
||||
{
|
||||
uri = stylesheet.getNamespaceURI(prefix);
|
||||
if (uri != null && uri.length() > 0)
|
||||
{
|
||||
String localName = keyName.getLocalPart();
|
||||
keyName = new QName(uri, localName, prefix);
|
||||
}
|
||||
}
|
||||
// Compute matching key set
|
||||
Collection keySet = new LinkedList();
|
||||
for (Iterator i = stylesheet.keys.iterator(); i.hasNext(); )
|
||||
{
|
||||
Key key = (Key) i.next();
|
||||
if (key.name.equals(keyName))
|
||||
{
|
||||
keySet.add(key);
|
||||
}
|
||||
}
|
||||
// Get target
|
||||
Object target = values.get(1);
|
||||
Collection acc = new LinkedHashSet();
|
||||
Document doc = (context instanceof Document) ? (Document) context :
|
||||
context.getOwnerDocument();
|
||||
if (target instanceof Collection)
|
||||
{
|
||||
for (Iterator i = ((Collection) target).iterator(); i.hasNext(); )
|
||||
{
|
||||
String val = Expr.stringValue((Node) i.next());
|
||||
addKeyNodes(doc, keySet, val, acc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String val = Expr._string(context, target);
|
||||
addKeyNodes(doc, keySet, val, acc);
|
||||
}
|
||||
List ret = new ArrayList(acc);
|
||||
Collections.sort(ret, documentOrderComparator);
|
||||
return ret;
|
||||
}
|
||||
|
||||
final void addKeyNodes(Node node, Collection keySet,
|
||||
String value, Collection acc)
|
||||
{
|
||||
addKeyNodeIfMatch(node, keySet, value, acc);
|
||||
// Apply children
|
||||
for (Node ctx = node.getFirstChild(); ctx != null;
|
||||
ctx = ctx.getNextSibling())
|
||||
{
|
||||
addKeyNodes(ctx, keySet, value, acc);
|
||||
}
|
||||
}
|
||||
|
||||
final void addKeyNodeIfMatch(Node node, Collection keySet,
|
||||
String value, Collection acc)
|
||||
{
|
||||
for (Iterator i = keySet.iterator(); i.hasNext(); )
|
||||
{
|
||||
Key key = (Key) i.next();
|
||||
if (key.match.matches(node))
|
||||
{
|
||||
Object eval = key.use.evaluate(node, 1, 1);
|
||||
if (eval instanceof Collection)
|
||||
{
|
||||
for (Iterator j = ((Collection) eval).iterator();
|
||||
j.hasNext(); )
|
||||
{
|
||||
String keyValue = Expr.stringValue((Node) j.next());
|
||||
if (value.equals(keyValue))
|
||||
{
|
||||
acc.add(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String keyValue = Expr._string(node, eval);
|
||||
if (value.equals(keyValue))
|
||||
{
|
||||
acc.add(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
Stylesheet s = stylesheet;
|
||||
if (context instanceof Stylesheet)
|
||||
{
|
||||
s = (Stylesheet) context;
|
||||
}
|
||||
KeyFunction f = new KeyFunction(s);
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
/* LiteralNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node that copies a DOM node in the template to the result
|
||||
* tree.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class LiteralNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
/**
|
||||
* The source node in the XSL template.
|
||||
*/
|
||||
final Node source;
|
||||
|
||||
final Collection elementExcludeResultPrefixes;
|
||||
|
||||
LiteralNode(TemplateNode children, TemplateNode next, Node source)
|
||||
{
|
||||
super(children, next);
|
||||
this.source = source;
|
||||
if (source.getNodeType() == Node.ELEMENT_NODE)
|
||||
{
|
||||
NamedNodeMap attrs = source.getAttributes();
|
||||
Node attr = attrs.getNamedItemNS(Stylesheet.XSL_NS,
|
||||
"exclude-result-prefixes");
|
||||
if (attr != null)
|
||||
{
|
||||
elementExcludeResultPrefixes = new HashSet();
|
||||
StringTokenizer st = new StringTokenizer(attr.getNodeValue());
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
elementExcludeResultPrefixes.add(st.nextToken());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementExcludeResultPrefixes = Collections.EMPTY_SET;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementExcludeResultPrefixes = null;
|
||||
}
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new LiteralNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
source);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Node result = null;
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
short nodeType = source.getNodeType();
|
||||
if (nodeType == Node.ATTRIBUTE_NODE &&
|
||||
parent.getFirstChild() != null)
|
||||
{
|
||||
// Ignore attributes added after child elements
|
||||
}
|
||||
else
|
||||
{
|
||||
// Namespace aliasing
|
||||
if (nodeType == Node.ELEMENT_NODE)
|
||||
{
|
||||
String prefix = source.getPrefix();
|
||||
if (prefix == null)
|
||||
{
|
||||
prefix = "#default";
|
||||
}
|
||||
String resultPrefix =
|
||||
(String) stylesheet.namespaceAliases.get(prefix);
|
||||
if (resultPrefix != null)
|
||||
{
|
||||
if ("#default".equals(resultPrefix))
|
||||
{
|
||||
resultPrefix = null;
|
||||
}
|
||||
String uri = source.lookupNamespaceURI(resultPrefix);
|
||||
String name = source.getNodeName();
|
||||
// Create a new element node in the result document
|
||||
result = doc.createElementNS(uri, name);
|
||||
// copy attributes
|
||||
NamedNodeMap srcAttrs = source.getAttributes();
|
||||
NamedNodeMap dstAttrs = result.getAttributes();
|
||||
int l = srcAttrs.getLength();
|
||||
for (int i = 0; i < l; i++)
|
||||
{
|
||||
Node attr = srcAttrs.item(i);
|
||||
if (!Stylesheet.XSL_NS.equals(attr.getNamespaceURI()))
|
||||
{
|
||||
attr = attr.cloneNode(true);
|
||||
attr = doc.adoptNode(attr);
|
||||
dstAttrs.setNamedItemNS(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
// Create result node
|
||||
result = source.cloneNode(false);
|
||||
// Remove any XSL attributes
|
||||
NamedNodeMap attrs = result.getAttributes();
|
||||
if (attrs != null)
|
||||
{
|
||||
int l = attrs.getLength();
|
||||
for (int i = 0; i < l; i++)
|
||||
{
|
||||
Node attr = attrs.item(i);
|
||||
if (Stylesheet.XSL_NS.equals(attr.getNamespaceURI()))
|
||||
{
|
||||
attrs.removeNamedItem(attr.getNodeName());
|
||||
i--;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
}
|
||||
result = doc.adoptNode(result);
|
||||
if (result == null)
|
||||
{
|
||||
String msg = "Error adopting node to result tree";
|
||||
DOMSourceLocator l = new DOMSourceLocator(context);
|
||||
throw new TransformerException(msg, l);
|
||||
}
|
||||
}
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(result, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(result);
|
||||
}
|
||||
if (nodeType == Node.ELEMENT_NODE)
|
||||
{
|
||||
stylesheet.addNamespaceNodes(source, result, doc,
|
||||
elementExcludeResultPrefixes);
|
||||
}
|
||||
// children
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
result, null);
|
||||
}
|
||||
}
|
||||
// next sibling
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("source=");
|
||||
buf.append(source);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/* MessageNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* An XSL <code>message</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class MessageNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final boolean terminate;
|
||||
|
||||
MessageNode(TemplateNode children, TemplateNode next, boolean terminate)
|
||||
{
|
||||
super(children, next);
|
||||
this.terminate = terminate;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new MessageNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
terminate);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
children.apply(stylesheet, mode, context, pos, len, fragment, null);
|
||||
String message = Expr.stringValue(fragment);
|
||||
System.err.println(message);
|
||||
if (terminate)
|
||||
{
|
||||
stylesheet.terminated = true;
|
||||
}
|
||||
}
|
||||
if (next != null && !terminate)
|
||||
{
|
||||
next.apply(stylesheet, mode, context, pos, len, parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/* NodeNumberNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.NodeTypeTest;
|
||||
import gnu.xml.xpath.Pattern;
|
||||
import gnu.xml.xpath.Selector;
|
||||
import gnu.xml.xpath.Test;
|
||||
import gnu.xml.xpath.UnionExpr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>number</code> instruction
|
||||
* with no <code>value</code> expression, i.e. the value is computed from
|
||||
* the document position of the context node.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class NodeNumberNode
|
||||
extends AbstractNumberNode
|
||||
{
|
||||
|
||||
static final int SINGLE = 0;
|
||||
static final int MULTIPLE = 1;
|
||||
static final int ANY = 2;
|
||||
|
||||
final int level;
|
||||
final Pattern count;
|
||||
final Pattern from;
|
||||
|
||||
NodeNumberNode(TemplateNode children, TemplateNode next,
|
||||
int level, Pattern count, Pattern from,
|
||||
TemplateNode format, String lang,
|
||||
int letterValue, String groupingSeparator, int groupingSize)
|
||||
{
|
||||
super(children, next, format, lang, letterValue, groupingSeparator,
|
||||
groupingSize);
|
||||
this.level = level;
|
||||
this.count = count;
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new NodeNumberNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
level,
|
||||
(count == null) ? null :
|
||||
(Pattern) count.clone(stylesheet),
|
||||
(from == null) ? from :
|
||||
(Pattern) from.clone(stylesheet),
|
||||
format, lang, letterValue,
|
||||
groupingSeparator, groupingSize);
|
||||
}
|
||||
|
||||
int[] compute(Stylesheet stylesheet, Node context, int pos, int len)
|
||||
throws TransformerException
|
||||
{
|
||||
/*if (from != null)
|
||||
{
|
||||
Object ret = from.evaluate(context, pos, len);
|
||||
if (ret instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) ret;
|
||||
if (ns.size() > 0)
|
||||
{
|
||||
List list = new ArrayList(ns);
|
||||
Collections.sort(list, documentOrderComparator);
|
||||
context = (Node) list.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new int[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new int[0];
|
||||
}
|
||||
}*/
|
||||
Node current = context;
|
||||
switch (level)
|
||||
{
|
||||
case SINGLE:
|
||||
if (from == null)
|
||||
{
|
||||
while (context != null && !countMatches(current, context))
|
||||
{
|
||||
context = context.getParentNode();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (context != null && !countMatches(current, context) &&
|
||||
!fromMatches(context))
|
||||
{
|
||||
context = context.getParentNode();
|
||||
}
|
||||
}
|
||||
return (context == null) ? new int[0] :
|
||||
new int[] { (context == current) ? pos : getIndex(current, context) };
|
||||
case MULTIPLE:
|
||||
List ancestors = new ArrayList();
|
||||
while (context != null)
|
||||
{
|
||||
if (countMatches(current, context))
|
||||
{
|
||||
if (from == null || fromMatches(context))
|
||||
{
|
||||
ancestors.add(context);
|
||||
}
|
||||
}
|
||||
context = context.getParentNode();
|
||||
}
|
||||
Collections.sort(ancestors, documentOrderComparator);
|
||||
int[] ret = new int[ancestors.size()];
|
||||
for (int i = 0; i < ret.length; i++)
|
||||
{
|
||||
ret[i] = getIndex(current, (Node) ancestors.get(i));
|
||||
}
|
||||
return ret;
|
||||
case ANY:
|
||||
Expr preceding = new Selector(Selector.PRECEDING,
|
||||
Collections.EMPTY_LIST);
|
||||
Expr ancestorOrSelf = new Selector(Selector.ANCESTOR_OR_SELF,
|
||||
Collections.EMPTY_LIST);
|
||||
Expr any = new UnionExpr(preceding, ancestorOrSelf);
|
||||
Object eval = any.evaluate(context, pos, len);
|
||||
if (eval instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) eval;
|
||||
List candidates = new ArrayList();
|
||||
for (Iterator i = ns.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node candidate = (Node) i.next();
|
||||
if (countMatches(current, candidate))
|
||||
{
|
||||
candidates.add(candidate);
|
||||
if (from != null && from.matches(candidate))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new int[] { candidates.size() };
|
||||
}
|
||||
return new int[0];
|
||||
default:
|
||||
throw new TransformerException("invalid level");
|
||||
}
|
||||
}
|
||||
|
||||
boolean countMatches(Node current, Node node)
|
||||
{
|
||||
if (count == null)
|
||||
{
|
||||
int cnt = current.getNodeType();
|
||||
int nnt = node.getNodeType();
|
||||
if (cnt != nnt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (nnt == Node.ELEMENT_NODE || nnt == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
String curi = current.getNamespaceURI();
|
||||
String nuri = node.getNamespaceURI();
|
||||
if ((curi == null && nuri != null) ||
|
||||
(curi != null && !curi.equals(nuri)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String cn = current.getLocalName();
|
||||
String nn = current.getLocalName();
|
||||
if (!cn.equals(nn))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return count.matches(node);
|
||||
}
|
||||
}
|
||||
|
||||
boolean fromMatches(Node node)
|
||||
{
|
||||
for (Node ctx = node.getParentNode(); ctx != null;
|
||||
ctx = ctx.getParentNode())
|
||||
{
|
||||
if (from.matches(ctx))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int getIndex(Node current, Node node)
|
||||
{
|
||||
int index = 0;
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
node = node.getPreviousSibling();
|
||||
}
|
||||
while (node != null && !countMatches(current, node));
|
||||
index++;
|
||||
}
|
||||
while (node != null);
|
||||
return index;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/* NumberNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>number</code> instruction
|
||||
* with a <code>value</code> expression.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class NumberNode
|
||||
extends AbstractNumberNode
|
||||
{
|
||||
|
||||
final Expr value;
|
||||
|
||||
NumberNode(TemplateNode children, TemplateNode next,
|
||||
Expr value, TemplateNode format, String lang,
|
||||
int letterValue, String groupingSeparator, int groupingSize)
|
||||
{
|
||||
super(children, next, format, lang, letterValue, groupingSeparator,
|
||||
groupingSize);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new NumberNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
value.clone(stylesheet),
|
||||
format, lang, letterValue,
|
||||
groupingSeparator, groupingSize);
|
||||
}
|
||||
|
||||
int[] compute(Stylesheet stylesheet, Node context, int pos, int len)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = value.evaluate(context, pos, len);
|
||||
Double d = (ret instanceof Double) ? ((Double) ret) :
|
||||
new Double(Expr._number(context, ret));
|
||||
return new int[] { d.intValue() };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/* OtherwiseNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>otherwise</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class OtherwiseNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
OtherwiseNode(TemplateNode children, TemplateNode next)
|
||||
{
|
||||
super(children, next);
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new OtherwiseNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet));
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/* ParameterNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.Collections;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node that sets a variable or parameter during template
|
||||
* processing.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ParameterNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final String name;
|
||||
final Expr select;
|
||||
final boolean global;
|
||||
|
||||
ParameterNode(TemplateNode children, TemplateNode next,
|
||||
String name, Expr select, boolean global)
|
||||
{
|
||||
super(children, next);
|
||||
this.name = name;
|
||||
this.select = select;
|
||||
this.global = global;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new ParameterNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
name,
|
||||
select.clone(stylesheet),
|
||||
global);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
boolean apply = global || !stylesheet.bindings.containsKey(name, global);
|
||||
if (apply)
|
||||
{
|
||||
// push the variable context
|
||||
stylesheet.bindings.push(global);
|
||||
// set the variable
|
||||
Object value = getValue(stylesheet, mode, context, pos, len);
|
||||
if (value != null)
|
||||
{
|
||||
stylesheet.bindings.set(name, value, global);
|
||||
}
|
||||
}
|
||||
// variable and param don't process children as such
|
||||
// all subsequent instructions are processed with that variable context
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (apply)
|
||||
{
|
||||
// pop the variable context
|
||||
stylesheet.bindings.pop(global);
|
||||
}
|
||||
}
|
||||
|
||||
Object getValue(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len)
|
||||
throws TransformerException
|
||||
{
|
||||
if (select != null)
|
||||
{
|
||||
return select.evaluate(context, pos, len);
|
||||
}
|
||||
else if (children != null)
|
||||
{
|
||||
Document doc = (context instanceof Document) ? (Document) context :
|
||||
context.getOwnerDocument();
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
children.apply(stylesheet, mode, context, pos, len, fragment, null);
|
||||
return Collections.singleton(fragment);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
if (select != null)
|
||||
{
|
||||
buf.append(",select=");
|
||||
buf.append(select);
|
||||
}
|
||||
if (global)
|
||||
{
|
||||
buf.append(",global");
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/* ProcessingInstructionNode.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.ProcessingInstruction;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>processing-instruction</code>
|
||||
* instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ProcessingInstructionNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final String name;
|
||||
|
||||
ProcessingInstructionNode(TemplateNode children, TemplateNode next,
|
||||
String name)
|
||||
{
|
||||
super(children, next);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new ProcessingInstructionNode((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
(next == null) ? null :
|
||||
next.clone(stylesheet),
|
||||
name);
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
String data = null;
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
if (children != null)
|
||||
{
|
||||
// Create a document fragment to hold the text
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply children to the fragment
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
data = Expr.stringValue(fragment);
|
||||
}
|
||||
ProcessingInstruction pi = doc.createProcessingInstruction(name, data);
|
||||
// Insert into result tree
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(pi, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(pi);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/* SAXSerializer.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Serializes a DOM node to a sequence of SAX events.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class SAXSerializer
|
||||
implements Attributes
|
||||
{
|
||||
|
||||
transient NamedNodeMap attrs;
|
||||
transient LinkedList namespaces = new LinkedList();
|
||||
|
||||
boolean isDefined(String prefix, String uri)
|
||||
{
|
||||
for (Iterator i = namespaces.iterator(); i.hasNext(); )
|
||||
{
|
||||
HashMap ctx = (HashMap) i.next();
|
||||
if (uri.equals(ctx.get(prefix)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void define(String prefix, String uri)
|
||||
{
|
||||
for (Iterator i = namespaces.iterator(); i.hasNext(); )
|
||||
{
|
||||
HashMap ctx = (HashMap) i.next();
|
||||
if (ctx.containsKey(prefix))
|
||||
{
|
||||
HashMap newCtx = new HashMap();
|
||||
newCtx.put(prefix, uri);
|
||||
namespaces.addFirst(newCtx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
HashMap ctx;
|
||||
if (namespaces.isEmpty())
|
||||
{
|
||||
ctx = new HashMap();
|
||||
namespaces.add(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx = (HashMap) namespaces.getFirst();
|
||||
}
|
||||
ctx.put(prefix, uri);
|
||||
}
|
||||
|
||||
void undefine(String prefix, String uri)
|
||||
{
|
||||
for (Iterator i = namespaces.iterator(); i.hasNext(); )
|
||||
{
|
||||
HashMap ctx = (HashMap) i.next();
|
||||
if (uri.equals(ctx.get(prefix)))
|
||||
{
|
||||
ctx.remove(prefix);
|
||||
if (ctx.isEmpty())
|
||||
{
|
||||
namespaces.remove(ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
return attrs.getLength();
|
||||
}
|
||||
|
||||
public String getURI(int index)
|
||||
{
|
||||
return attrs.item(index).getNamespaceURI();
|
||||
}
|
||||
|
||||
public String getLocalName(int index)
|
||||
{
|
||||
return attrs.item(index).getLocalName();
|
||||
}
|
||||
|
||||
public String getQName(int index)
|
||||
{
|
||||
return attrs.item(index).getNodeName();
|
||||
}
|
||||
|
||||
public String getType(int index)
|
||||
{
|
||||
Attr attr = (Attr) attrs.item(index);
|
||||
return attr.isId() ? "ID" : "CDATA";
|
||||
}
|
||||
|
||||
public String getValue(int index)
|
||||
{
|
||||
return attrs.item(index).getNodeValue();
|
||||
}
|
||||
|
||||
public int getIndex(String uri, String localName)
|
||||
{
|
||||
int len = attrs.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node attr = attrs.item(i);
|
||||
String a_uri = attr.getNamespaceURI();
|
||||
String a_localName = attr.getLocalName();
|
||||
if (((a_uri == null && uri == null) ||
|
||||
(a_uri != null && a_uri.equals(uri))) &&
|
||||
a_localName.equals(localName))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getIndex(String qName)
|
||||
{
|
||||
int len = attrs.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node attr = attrs.item(i);
|
||||
String a_name = attr.getNodeName();
|
||||
if (a_name.equals(qName))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String getType(String uri, String localName)
|
||||
{
|
||||
Attr attr = (Attr) attrs.getNamedItemNS(uri, localName);
|
||||
return attr.isId() ? "ID" : "CDATA";
|
||||
}
|
||||
|
||||
public String getType(String qName)
|
||||
{
|
||||
Attr attr = (Attr) attrs.getNamedItem(qName);
|
||||
return attr.isId() ? "ID" : "CDATA";
|
||||
}
|
||||
|
||||
public String getValue(String uri, String localName)
|
||||
{
|
||||
return attrs.getNamedItemNS(uri, localName).getNodeValue();
|
||||
}
|
||||
|
||||
public String getValue(String qName)
|
||||
{
|
||||
return attrs.getNamedItem(qName).getNodeValue();
|
||||
}
|
||||
|
||||
void serialize(Node node, ContentHandler ch, LexicalHandler lh)
|
||||
throws SAXException
|
||||
{
|
||||
attrs = node.getAttributes();
|
||||
Node children;
|
||||
Node next = node.getNextSibling();
|
||||
switch (node.getNodeType())
|
||||
{
|
||||
case Node.ELEMENT_NODE:
|
||||
String uri = node.getNamespaceURI();
|
||||
String prefix = node.getPrefix();
|
||||
boolean defined = isDefined(prefix, uri);
|
||||
if (!defined)
|
||||
{
|
||||
define(prefix, uri);
|
||||
ch.startPrefixMapping(prefix, uri);
|
||||
}
|
||||
String localName = node.getLocalName();
|
||||
String qName = node.getNodeName();
|
||||
ch.startElement(uri, localName, qName, this);
|
||||
children = node.getFirstChild();
|
||||
if (children != null)
|
||||
{
|
||||
serialize(children, ch, lh);
|
||||
}
|
||||
ch.endElement(uri, localName, qName);
|
||||
if (!defined)
|
||||
{
|
||||
ch.endPrefixMapping(prefix);
|
||||
undefine(prefix, uri);
|
||||
}
|
||||
break;
|
||||
case Node.TEXT_NODE:
|
||||
char[] chars = node.getNodeValue().toCharArray();
|
||||
ch.characters(chars, 0, chars.length);
|
||||
break;
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
char[] cdata = node.getNodeValue().toCharArray();
|
||||
if (lh != null)
|
||||
{
|
||||
lh.startCDATA();
|
||||
ch.characters(cdata, 0, cdata.length);
|
||||
lh.endCDATA();
|
||||
}
|
||||
else
|
||||
{
|
||||
ch.characters(cdata, 0, cdata.length);
|
||||
}
|
||||
break;
|
||||
case Node.COMMENT_NODE:
|
||||
if (lh != null)
|
||||
{
|
||||
char[] comment = node.getNodeValue().toCharArray();
|
||||
lh.comment(comment, 0, comment.length);
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_NODE:
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
ch.startDocument();
|
||||
children = node.getFirstChild();
|
||||
if (children != null)
|
||||
{
|
||||
serialize(children, ch, lh);
|
||||
}
|
||||
ch.endDocument();
|
||||
break;
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
if (lh != null)
|
||||
{
|
||||
DocumentType doctype = (DocumentType) node;
|
||||
String publicId = doctype.getPublicId();
|
||||
String systemId = doctype.getSystemId();
|
||||
lh.startDTD(node.getNodeName(), publicId, systemId);
|
||||
NamedNodeMap entities = doctype.getEntities();
|
||||
int len = entities.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node entity = entities.item(i);
|
||||
String entityName = entity.getNodeName();
|
||||
lh.startEntity(entityName);
|
||||
lh.endEntity(entityName);
|
||||
}
|
||||
lh.endDTD();
|
||||
}
|
||||
break;
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
ch.processingInstruction(node.getNodeName(), node.getNodeValue());
|
||||
break;
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
ch.skippedEntity(node.getNodeName());
|
||||
break;
|
||||
}
|
||||
attrs = null;
|
||||
if (next != null)
|
||||
{
|
||||
serialize(next, ch, lh);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/* SortKey.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* An XSL sort key.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class SortKey
|
||||
{
|
||||
|
||||
static final int DEFAULT = 0;
|
||||
static final int UPPER_FIRST = 1;
|
||||
static final int LOWER_FIRST = 2;
|
||||
|
||||
final Expr select;
|
||||
final TemplateNode langTemplate;
|
||||
final TemplateNode dataTypeTemplate;
|
||||
final TemplateNode orderTemplate;
|
||||
final TemplateNode caseOrderTemplate;
|
||||
|
||||
transient String lang;
|
||||
transient String dataType;
|
||||
transient boolean descending;
|
||||
transient int caseOrder;
|
||||
|
||||
SortKey(Expr select, TemplateNode lang, TemplateNode dataType,
|
||||
TemplateNode order, TemplateNode caseOrder)
|
||||
{
|
||||
this.select = select;
|
||||
this.langTemplate = lang;
|
||||
this.dataTypeTemplate = dataType;
|
||||
this.orderTemplate = order;
|
||||
this.caseOrderTemplate = caseOrder;
|
||||
}
|
||||
|
||||
String key(Node node)
|
||||
{
|
||||
Object ret = select.evaluate(node, 1, 1);
|
||||
if (ret instanceof String)
|
||||
{
|
||||
return (String) ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Expr._string(node, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare for a sort.
|
||||
* This sets all transient variables from their AVTs.
|
||||
*/
|
||||
void init(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Document doc = (context instanceof Document) ? (Document) context :
|
||||
context.getOwnerDocument();
|
||||
if (langTemplate == null)
|
||||
{
|
||||
lang = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
langTemplate.apply(stylesheet, mode, context, pos, len,
|
||||
fragment, null);
|
||||
lang = Expr.stringValue(fragment);
|
||||
}
|
||||
if (dataTypeTemplate == null)
|
||||
{
|
||||
dataType = "text";
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
dataTypeTemplate.apply(stylesheet, mode, context, pos, len,
|
||||
fragment, null);
|
||||
dataType = Expr.stringValue(fragment);
|
||||
}
|
||||
if (orderTemplate == null)
|
||||
{
|
||||
descending = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
orderTemplate.apply(stylesheet, mode, context, pos, len,
|
||||
fragment, null);
|
||||
String order = Expr.stringValue(fragment);
|
||||
descending = "descending".equals(order);
|
||||
}
|
||||
if (caseOrderTemplate == null)
|
||||
{
|
||||
caseOrder = DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
caseOrderTemplate.apply(stylesheet, mode, context, pos, len,
|
||||
fragment, null);
|
||||
String co = Expr.stringValue(fragment);
|
||||
caseOrder = "upper-first".equals(co) ? UPPER_FIRST :
|
||||
"lower-first".equals(co) ? LOWER_FIRST :
|
||||
DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,632 @@
|
||||
/* StreamSerializer.java --
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.xml.transform;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.xml.XMLConstants;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Serializes a DOM node to an output stream.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class StreamSerializer
|
||||
{
|
||||
|
||||
static final int SPACE = 0x20;
|
||||
static final int BANG = 0x21; // !
|
||||
static final int APOS = 0x27; // '
|
||||
static final int SLASH = 0x2f; // /
|
||||
static final int BRA = 0x3c; // <
|
||||
static final int KET = 0x3e; // >
|
||||
static final int EQ = 0x3d; // =
|
||||
|
||||
protected String encoding;
|
||||
boolean compatibilityMode;
|
||||
final int mode;
|
||||
final Map namespaces;
|
||||
protected String eol;
|
||||
Collection cdataSectionElements = Collections.EMPTY_SET;
|
||||
|
||||
protected boolean discardDefaultContent;
|
||||
protected boolean xmlDeclaration = true;
|
||||
|
||||
public StreamSerializer()
|
||||
{
|
||||
this(Stylesheet.OUTPUT_XML, null, null);
|
||||
}
|
||||
|
||||
public StreamSerializer(String encoding)
|
||||
{
|
||||
this(Stylesheet.OUTPUT_XML, encoding, null);
|
||||
}
|
||||
|
||||
public StreamSerializer(int mode, String encoding, String eol)
|
||||
{
|
||||
this.mode = mode;
|
||||
if (encoding == null)
|
||||
{
|
||||
encoding = "UTF-8";
|
||||
}
|
||||
this.encoding = encoding.intern();
|
||||
compatibilityMode = true;
|
||||
if (encoding.length() > 3)
|
||||
{
|
||||
String p = encoding.substring(0, 3);
|
||||
if (p.equalsIgnoreCase("UTF") ||
|
||||
p.equalsIgnoreCase("UCS"))
|
||||
{
|
||||
compatibilityMode = false;
|
||||
}
|
||||
}
|
||||
this.eol = (eol != null) ? eol : System.getProperty("line.separator");
|
||||
namespaces = new HashMap();
|
||||
}
|
||||
|
||||
void setCdataSectionElements(Collection c)
|
||||
{
|
||||
cdataSectionElements = c;
|
||||
}
|
||||
|
||||
public void serialize(final Node node, final OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
serialize(node, out, false);
|
||||
}
|
||||
|
||||
void serialize(final Node node, final OutputStream out,
|
||||
boolean convertToCdata)
|
||||
throws IOException
|
||||
{
|
||||
if (out == null)
|
||||
{
|
||||
throw new NullPointerException("no output stream");
|
||||
}
|
||||
String value, prefix;
|
||||
Node children;
|
||||
Node next = node.getNextSibling();
|
||||
String uri = node.getNamespaceURI();
|
||||
boolean defined = false;
|
||||
short nt = node.getNodeType();
|
||||
if (convertToCdata && nt == Node.TEXT_NODE)
|
||||
{
|
||||
nt = Node.CDATA_SECTION_NODE;
|
||||
}
|
||||
switch (nt)
|
||||
{
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
prefix = node.getPrefix();
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
|
||||
XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) ||
|
||||
(prefix != null && prefix.startsWith("xmlns:")))
|
||||
{
|
||||
String nsuri = node.getNodeValue();
|
||||
if (isDefined(nsuri))
|
||||
{
|
||||
break;
|
||||
}
|
||||
define(nsuri, node.getLocalName());
|
||||
}
|
||||
else if (uri != null && !isDefined(uri))
|
||||
{
|
||||
prefix = define(uri, prefix);
|
||||
String nsname = (prefix == null) ? "xmlns" : "xmlns:" + prefix;
|
||||
out.write(SPACE);
|
||||
out.write(encodeText(nsname));
|
||||
out.write(EQ);
|
||||
String nsvalue = "'" + encode(uri, true, true) + "'";
|
||||
out.write(nsvalue.getBytes(encoding));
|
||||
defined = true;
|
||||
}
|
||||
out.write(SPACE);
|
||||
String a_nodeName = node.getNodeName();
|
||||
out.write(encodeText(a_nodeName));
|
||||
String a_nodeValue = node.getNodeValue();
|
||||
if (mode == Stylesheet.OUTPUT_HTML &&
|
||||
a_nodeName.equals(a_nodeValue))
|
||||
{
|
||||
break;
|
||||
}
|
||||
out.write(EQ);
|
||||
value = "'" + encode(a_nodeValue, true, true) + "'";
|
||||
out.write(encodeText(value));
|
||||
break;
|
||||
case Node.ELEMENT_NODE:
|
||||
value = node.getNodeName();
|
||||
out.write(BRA);
|
||||
out.write(encodeText(value));
|
||||
if (uri != null && !isDefined(uri))
|
||||
{
|
||||
prefix = define(uri, node.getPrefix());
|
||||
String nsname = (prefix == null) ? "xmlns" : "xmlns:" + prefix;
|
||||
out.write(SPACE);
|
||||
out.write(encodeText(nsname));
|
||||
out.write(EQ);
|
||||
String nsvalue = "'" + encode(uri, true, true) + "'";
|
||||
out.write(encodeText(nsvalue));
|
||||
defined = true;
|
||||
}
|
||||
NamedNodeMap attrs = node.getAttributes();
|
||||
if (attrs != null)
|
||||
{
|
||||
int len = attrs.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Attr attr = (Attr) attrs.item(i);
|
||||
if (discardDefaultContent && !attr.getSpecified())
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
else
|
||||
{
|
||||
serialize(attr, out, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
convertToCdata = cdataSectionElements.contains(value);
|
||||
children = node.getFirstChild();
|
||||
if (children == null)
|
||||
{
|
||||
out.write(SLASH);
|
||||
out.write(KET);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write(KET);
|
||||
serialize(children, out, convertToCdata);
|
||||
out.write(BRA);
|
||||
out.write(SLASH);
|
||||
out.write(encodeText(value));
|
||||
out.write(KET);
|
||||
}
|
||||
break;
|
||||
case Node.TEXT_NODE:
|
||||
value = node.getNodeValue();
|
||||
if (!"yes".equals(node.getUserData("disable-output-escaping")))
|
||||
{
|
||||
value = encode(value, false, false);
|
||||
}
|
||||
out.write(encodeText(value));
|
||||
break;
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
value = "<![CDATA[" + node.getNodeValue() + "]]>";
|
||||
out.write(encodeText(value));
|
||||
break;
|
||||
case Node.COMMENT_NODE:
|
||||
value = "<!--" + node.getNodeValue() + "-->";
|
||||
out.write(encodeText(value));
|
||||
Node cp = node.getParentNode();
|
||||
if (cp != null && cp.getNodeType() == Node.DOCUMENT_NODE)
|
||||
{
|
||||
out.write(encodeText(eol));
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_NODE:
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
if (mode == Stylesheet.OUTPUT_XML)
|
||||
{
|
||||
if ("UTF-16".equalsIgnoreCase(encoding))
|
||||
{
|
||||
out.write(0xfe);
|
||||
out.write(0xff);
|
||||
}
|
||||
if (!"yes".equals(node.getUserData("omit-xml-declaration")) &&
|
||||
xmlDeclaration)
|
||||
{
|
||||
Document doc = (node instanceof Document) ?
|
||||
(Document) node : null;
|
||||
String version = (doc != null) ? doc.getXmlVersion() : null;
|
||||
if (version == null)
|
||||
{
|
||||
version = (String) node.getUserData("version");
|
||||
}
|
||||
if (version == null)
|
||||
{
|
||||
version = "1.0";
|
||||
}
|
||||
out.write(BRA);
|
||||
out.write(0x3f);
|
||||
out.write("xml version='".getBytes("US-ASCII"));
|
||||
out.write(version.getBytes("US-ASCII"));
|
||||
out.write(APOS);
|
||||
if (!("UTF-8".equalsIgnoreCase(encoding)))
|
||||
{
|
||||
out.write(" encoding='".getBytes("US-ASCII"));
|
||||
out.write(encoding.getBytes("US-ASCII"));
|
||||
out.write(APOS);
|
||||
}
|
||||
if ((doc != null && doc.getXmlStandalone()) ||
|
||||
"yes".equals(node.getUserData("standalone")))
|
||||
{
|
||||
out.write(" standalone='yes'".getBytes("US-ASCII"));
|
||||
}
|
||||
out.write(0x3f);
|
||||
out.write(KET);
|
||||
out.write(encodeText(eol));
|
||||
}
|
||||
// TODO warn if not outputting the declaration would be a
|
||||
// problem
|
||||
}
|
||||
else if (mode == Stylesheet.OUTPUT_HTML)
|
||||
{
|
||||
// Ensure that encoding is accessible
|
||||
String mediaType = (String) node.getUserData("media-type");
|
||||
if (mediaType == null)
|
||||
{
|
||||
mediaType = "text/html";
|
||||
}
|
||||
String contentType = mediaType + "; charset=" +
|
||||
((encoding.indexOf(' ') != -1) ?
|
||||
"\"" + encoding + "\"" :
|
||||
encoding);
|
||||
Document doc = (node instanceof Document) ? (Document) node :
|
||||
node.getOwnerDocument();
|
||||
Node html = null;
|
||||
for (Node ctx = node.getFirstChild(); ctx != null;
|
||||
ctx = ctx.getNextSibling())
|
||||
{
|
||||
if (ctx.getNodeType() == Node.ELEMENT_NODE)
|
||||
{
|
||||
html = ctx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (html == null)
|
||||
{
|
||||
html = doc.createElement("html");
|
||||
node.appendChild(html);
|
||||
}
|
||||
Node head = null;
|
||||
for (Node ctx = html.getFirstChild(); ctx != null;
|
||||
ctx = ctx.getNextSibling())
|
||||
{
|
||||
if (ctx.getNodeType() == Node.ELEMENT_NODE &&
|
||||
"head".equalsIgnoreCase(ctx.getLocalName()))
|
||||
{
|
||||
head = ctx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (head == null)
|
||||
{
|
||||
head = doc.createElement("head");
|
||||
Node c1 = null;
|
||||
for (Node ctx = html.getFirstChild(); ctx != null;
|
||||
ctx = ctx.getNextSibling())
|
||||
{
|
||||
if (ctx.getNodeType() == Node.ELEMENT_NODE)
|
||||
{
|
||||
c1 = ctx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c1 != null)
|
||||
{
|
||||
html.insertBefore(head, c1);
|
||||
}
|
||||
else
|
||||
{
|
||||
html.appendChild(head);
|
||||
}
|
||||
}
|
||||
Node meta = null;
|
||||
Node metaContent = null;
|
||||
for (Node ctx = head.getFirstChild(); ctx != null;
|
||||
ctx = ctx.getNextSibling())
|
||||
{
|
||||
if (ctx.getNodeType() == Node.ELEMENT_NODE &&
|
||||
"meta".equalsIgnoreCase(ctx.getLocalName()))
|
||||
{
|
||||
NamedNodeMap metaAttrs = ctx.getAttributes();
|
||||
int len = metaAttrs.getLength();
|
||||
String httpEquiv = null;
|
||||
Node content = null;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node attr = metaAttrs.item(i);
|
||||
String attrName = attr.getNodeName();
|
||||
if ("http-equiv".equalsIgnoreCase(attrName))
|
||||
{
|
||||
httpEquiv = attr.getNodeValue();
|
||||
}
|
||||
else if ("content".equalsIgnoreCase(attrName))
|
||||
{
|
||||
content = attr;
|
||||
}
|
||||
}
|
||||
if ("Content-Type".equalsIgnoreCase(httpEquiv))
|
||||
{
|
||||
meta = ctx;
|
||||
metaContent = content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (meta == null)
|
||||
{
|
||||
meta = doc.createElement("meta");
|
||||
// Insert first
|
||||
Node first = head.getFirstChild();
|
||||
if (first == null)
|
||||
{
|
||||
head.appendChild(meta);
|
||||
}
|
||||
else
|
||||
{
|
||||
head.insertBefore(meta, first);
|
||||
}
|
||||
Node metaHttpEquiv = doc.createAttribute("http-equiv");
|
||||
meta.getAttributes().setNamedItem(metaHttpEquiv);
|
||||
metaHttpEquiv.setNodeValue("Content-Type");
|
||||
}
|
||||
if (metaContent == null)
|
||||
{
|
||||
metaContent = doc.createAttribute("content");
|
||||
meta.getAttributes().setNamedItem(metaContent);
|
||||
}
|
||||
metaContent.setNodeValue(contentType);
|
||||
// phew
|
||||
}
|
||||
children = node.getFirstChild();
|
||||
if (children != null)
|
||||
{
|
||||
serialize(children, out, convertToCdata);
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
DocumentType doctype = (DocumentType) node;
|
||||
out.write(BRA);
|
||||
out.write(BANG);
|
||||
value = doctype.getNodeName();
|
||||
out.write(encodeText(value));
|
||||
String publicId = doctype.getPublicId();
|
||||
if (publicId != null)
|
||||
{
|
||||
out.write(encodeText(" PUBLIC "));
|
||||
out.write(APOS);
|
||||
out.write(encodeText(publicId));
|
||||
out.write(APOS);
|
||||
}
|
||||
String systemId = doctype.getSystemId();
|
||||
if (systemId != null)
|
||||
{
|
||||
out.write(encodeText(" SYSTEM "));
|
||||
out.write(APOS);
|
||||
out.write(encodeText(systemId));
|
||||
out.write(APOS);
|
||||
}
|
||||
String internalSubset = doctype.getInternalSubset();
|
||||
if (internalSubset != null)
|
||||
{
|
||||
out.write(encodeText(internalSubset));
|
||||
}
|
||||
out.write(KET);
|
||||
out.write(eol.getBytes(encoding));
|
||||
break;
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
value = "&" + node.getNodeValue() + ";";
|
||||
out.write(encodeText(value));
|
||||
break;
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
value = "<?" + node.getNodeName() + " " + node.getNodeValue() + "?>";
|
||||
out.write(encodeText(value));
|
||||
Node pp = node.getParentNode();
|
||||
if (pp != null && pp.getNodeType() == Node.DOCUMENT_NODE)
|
||||
{
|
||||
out.write(encodeText(eol));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (defined)
|
||||
{
|
||||
undefine(uri);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
serialize(next, out, convertToCdata);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isDefined(String uri)
|
||||
{
|
||||
return XMLConstants.XML_NS_URI.equals(uri) ||
|
||||
XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
|
||||
namespaces.containsKey(uri);
|
||||
}
|
||||
|
||||
String define(String uri, String prefix)
|
||||
{
|
||||
while (namespaces.containsValue(prefix))
|
||||
{
|
||||
// Fabricate new prefix
|
||||
prefix = prefix + "_";
|
||||
}
|
||||
namespaces.put(uri, prefix);
|
||||
return prefix;
|
||||
}
|
||||
|
||||
void undefine(String uri)
|
||||
{
|
||||
namespaces.remove(uri);
|
||||
}
|
||||
|
||||
final byte[] encodeText(String text)
|
||||
throws UnsupportedEncodingException
|
||||
{
|
||||
if (compatibilityMode)
|
||||
{
|
||||
int len = text.length();
|
||||
StringBuffer buf = null;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = text.charAt(i);
|
||||
if (c >= 127)
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append('&');
|
||||
buf.append('#');
|
||||
buf.append((int) c);
|
||||
buf.append(';');
|
||||
}
|
||||
else if (buf != null)
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
if (buf != null)
|
||||
{
|
||||
text = buf.toString();
|
||||
}
|
||||
}
|
||||
return text.getBytes(encoding);
|
||||
}
|
||||
|
||||
String encode(String text, boolean encodeCtl, boolean inAttr)
|
||||
{
|
||||
int len = text.length();
|
||||
StringBuffer buf = null;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = text.charAt(i);
|
||||
if (c == '<')
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append("<");
|
||||
}
|
||||
else if (c == '>')
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append(">");
|
||||
}
|
||||
else if (c == '&')
|
||||
{
|
||||
if (mode == Stylesheet.OUTPUT_HTML && (i + 1) < len &&
|
||||
text.charAt(i + 1) == '{')
|
||||
{
|
||||
if (buf != null)
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append("&");
|
||||
}
|
||||
}
|
||||
else if (c == '\'' && inAttr)
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append("'");
|
||||
}
|
||||
else if (c == '"' && inAttr)
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append(""");
|
||||
}
|
||||
else if (encodeCtl)
|
||||
{
|
||||
if (c < 0x20)
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append('&');
|
||||
buf.append('#');
|
||||
buf.append((int) c);
|
||||
buf.append(';');
|
||||
}
|
||||
else if (buf != null)
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
else if (buf != null)
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
return (buf == null) ? text : buf.toString();
|
||||
}
|
||||
|
||||
String toString(Node node)
|
||||
{
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
serialize(node, out);
|
||||
return new String(out.toByteArray(), encoding);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user