Author: rhauch
Date: 2008-11-11 23:31:14 -0500 (Tue, 11 Nov 2008)
New Revision: 619
Added:
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencer.java
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithCDATA.xml
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithComments.xml
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithDtdEntities.xml
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespaces.xml
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespacesWithoutDefault.xml
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNestedNamespaces.xml
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithOnlyRootElement.xml
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithProcessingInstructions.xml
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithoutNamespaces.xml
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerContext.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerOutput.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java
Log:
DNA-223 - XML sequencer does not properly handle namespaces of unqualified attributes
http://jira.jboss.com/jira/browse/DNA-223
It is not really possible to correctly handle unqualified attributes in a general manner
if we consider the XML Schema specification. This is because an XML schema by default
will require that unqualified attributes inherit the element's namespace, and because
within any single XML schema it is possible to define one element that requires
unqualified attributes inherit the element's namespace while other element definitions
require that unqualified attributes use the default namespace. In other words, a
general-purpose sequencer cannot always do the "correct" thing without
thoroughly understanding the XML Schema(s) used by an XML document.
Therefore, this has been addressed by changing the XML sequencer to be configurable as to
the desired behavior. Note that this behavior is fixed for a particular document, and
still won't properly handle an XML document that uses a schema with a mixture of
qualified and unqualified attribute forms. The default is to use the default namespace
(at that position in the document), which is really the default for XML documents. To
make it easy to specify a sequencer by classname that inherits the element's namespace
for unqualified attributes, there is also a new InheritingXmlSequencer, which extends
XmlSequencer and simply overrides the default setting.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java 2008-11-10
23:57:53 UTC (rev 618)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -156,8 +156,7 @@
}
public void create( Path path,
- List<Property> properties,
- Name elementName ) {
+ List<Property> properties ) {
assert properties != null;
if (properties.isEmpty()) {
batch.create(path).and();
@@ -166,6 +165,16 @@
}
}
+ public void create( Path path,
+ Property firstProperty,
+ Property... additionalProperties ) {
+ if (firstProperty == null) {
+ batch.create(path).and();
+ } else {
+ batch.create(path, firstProperty, additionalProperties);
+ }
+ }
+
public void submit() {
}
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java 2008-11-10
23:57:53 UTC (rev 618)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -53,6 +53,8 @@
public static final Path ROOT = new BasicPath(EMPTY_SEGMENTS, true);
+ public static final Path EMPTY_RELATIVE = new BasicPath(EMPTY_SEGMENTS, false);
+
public static final Path SELF_PATH = new
BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
private final List<Segment> segments;
@@ -84,7 +86,7 @@
*/
public Path getParent() {
if (this.isRoot()) return null;
- if (this.segments.size() == 1) return ROOT;
+ if (this.segments.size() == 1) return this.isAbsolute() ? ROOT : EMPTY_RELATIVE;
return subpath(0, this.segments.size() - 1);
}
@@ -96,6 +98,7 @@
if (degree == 0) return this;
if (this.isRoot()) return null;
int endIndex = this.segments.size() - degree;
+ if (endIndex == 0) return this.isAbsolute() ? ROOT : EMPTY_RELATIVE;
if (endIndex < 0) {
String msg = GraphI18n.pathAncestorDegreeIsInvalid.text(this.getString(),
Inflector.getInstance().ordinalize(degree));
throw new InvalidPathException(msg);
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java 2008-11-10
23:57:53 UTC (rev 618)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -169,9 +169,10 @@
* {@inheritDoc}
*/
public Path create( int value ) {
- throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
Integer.class.getSimpleName(),
-
value));
+ throw new ValueFormatException(value, getPropertyType(),
+
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+
Integer.class.getSimpleName(),
+ value));
}
/**
@@ -179,17 +180,18 @@
*/
public Path create( long value ) {
throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
Long.class.getSimpleName(),
-
value));
+
Long.class.getSimpleName(),
+
value));
}
/**
* {@inheritDoc}
*/
public Path create( boolean value ) {
- throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
Boolean.class.getSimpleName(),
-
value));
+ throw new ValueFormatException(value, getPropertyType(),
+
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+
Boolean.class.getSimpleName(),
+ value));
}
/**
@@ -197,8 +199,8 @@
*/
public Path create( float value ) {
throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
Float.class.getSimpleName(),
-
value));
+
Float.class.getSimpleName(),
+
value));
}
/**
@@ -206,8 +208,8 @@
*/
public Path create( double value ) {
throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
Double.class.getSimpleName(),
-
value));
+
Double.class.getSimpleName(),
+
value));
}
/**
@@ -216,17 +218,18 @@
public Path create( BigDecimal value ) {
throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
BigDecimal.class.getSimpleName(),
- value));
+
BigDecimal.class.getSimpleName(),
+ value));
}
/**
* {@inheritDoc}
*/
public Path create( Calendar value ) {
- throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
Calendar.class.getSimpleName(),
-
value));
+ throw new ValueFormatException(value, getPropertyType(),
+
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+
Calendar.class.getSimpleName(),
+ value));
}
/**
@@ -234,8 +237,8 @@
*/
public Path create( Date value ) {
throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
Date.class.getSimpleName(),
-
value));
+
Date.class.getSimpleName(),
+
value));
}
/**
@@ -244,9 +247,10 @@
* @see
org.jboss.dna.graph.properties.ValueFactory#create(org.jboss.dna.graph.properties.DateTime)
*/
public Path create( DateTime value ) throws ValueFormatException {
- throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
DateTime.class.getSimpleName(),
-
value));
+ throw new ValueFormatException(value, getPropertyType(),
+
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
+
DateTime.class.getSimpleName(),
+ value));
}
/**
@@ -325,14 +329,14 @@
* @see org.jboss.dna.graph.properties.PathFactory#createRelativePath()
*/
public Path createRelativePath() {
- return BasicPath.SELF_PATH;
+ return BasicPath.EMPTY_RELATIVE;
}
/**
* {@inheritDoc}
*/
public Path createRelativePath( Name... segmentNames ) {
- if (segmentNames == null || segmentNames.length == 0) return
BasicPath.SELF_PATH;
+ if (segmentNames == null || segmentNames.length == 0) return
BasicPath.EMPTY_RELATIVE;
List<Segment> segments = new
ArrayList<Segment>(segmentNames.length);
for (Name segmentName : segmentNames) {
if (segmentName == null) {
@@ -347,7 +351,7 @@
* {@inheritDoc}
*/
public Path createRelativePath( Segment... segments ) {
- if (segments == null || segments.length == 0) return BasicPath.SELF_PATH;
+ if (segments == null || segments.length == 0) return BasicPath.EMPTY_RELATIVE;
List<Segment> segmentsList = new
ArrayList<Segment>(segments.length);
for (Segment segment : segments) {
if (segment == null) {
@@ -371,14 +375,15 @@
}
segmentsList.add(segment);
}
- if (segmentsList.isEmpty()) return BasicPath.SELF_PATH;
+ if (segmentsList.isEmpty()) return BasicPath.EMPTY_RELATIVE;
return new BasicPath(segmentsList, false);
}
/**
* {@inheritDoc}
*
- * @see
org.jboss.dna.graph.properties.PathFactory#create(org.jboss.dna.graph.properties.Path,
org.jboss.dna.graph.properties.Path)
+ * @see
org.jboss.dna.graph.properties.PathFactory#create(org.jboss.dna.graph.properties.Path,
+ * org.jboss.dna.graph.properties.Path)
*/
public Path create( Path parentPath,
Path childPath ) {
@@ -538,7 +543,7 @@
Integer.parseInt(ndx));
} catch (NumberFormatException err) {
throw new ValueFormatException(segmentName, getPropertyType(),
GraphI18n.invalidIndexInSegmentName.text(ndx,
-
segmentName));
+
segmentName));
}
}
@@ -559,8 +564,8 @@
public Path create( Reference value ) {
throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
Reference.class.getSimpleName(),
- value));
+
Reference.class.getSimpleName(),
+ value));
}
/**
@@ -577,8 +582,8 @@
return create(asciiString);
}
throw new ValueFormatException(value, getPropertyType(),
GraphI18n.errorConvertingType.text(URI.class.getSimpleName(),
-
Path.class.getSimpleName(),
-
value));
+
Path.class.getSimpleName(),
+
value));
}
/**
@@ -588,8 +593,8 @@
*/
public Path create( UUID value ) {
throw new ValueFormatException(value, getPropertyType(),
GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
-
UUID.class.getSimpleName(),
-
value));
+
UUID.class.getSimpleName(),
+
value));
}
/**
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java 2008-11-10
23:57:53 UTC (rev 618)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -311,7 +311,7 @@
properties.clear();
Object typePropertyValue = null;
// Convert each of the attributes to a property ...
- for (int i = 0; i != attributes.getLength(); ++i) {
+ for (int i = 0, len = attributes.getLength(); i != len; ++i) {
String attributeLocalName = attributes.getLocalName(i);
String attributeUri = attributes.getURI(i);
Name attributeName = null;
@@ -333,7 +333,7 @@
nodeName = nameFactory.create(attributes.getValue(i)); // don't use a
decoder
continue;
}
- if (attributeName.equals(typeAttribute)) {
+ if (typePropertyValue == null && attributeName.equals(typeAttribute))
{
typePropertyValue = nameFactory.create(attributes.getValue(i)); //
don't use a decoder
continue;
}
@@ -342,25 +342,25 @@
properties.add(property);
}
// Create the node name if required ...
- Name elementName = nameFactory.create(uri, localName, decoder);
if (nodeName == null) {
// No attribute defines the node name ...
- nodeName = elementName;
+ nodeName = nameFactory.create(uri, localName, decoder);
} else {
- // A attribute defines the node name ...
- typePropertyValue = elementName;
+ typePropertyValue = nameFactory.create(uri, localName, decoder);
}
- // Set the type property, if required
if (typeAttribute != null) {
+ // A attribute defines the node name. Set the type property, if required
if (typePropertyValue == null) typePropertyValue = typeAttributeValue;
- propertyValues[0] = typePropertyValue;
- Property property = propertyFactory.create(typeAttribute, propertyValues);
- properties.add(property);
+ if (typePropertyValue != null) {
+ propertyValues[0] = typePropertyValue;
+ Property property = propertyFactory.create(typeAttribute,
propertyValues);
+ properties.add(property);
+ }
}
// Update the current path ...
currentPath = pathFactory.create(currentPath, nodeName);
// Create the node, and note that we don't care about same-name siblings (as
the graph will correct them) ...
- destination.create(currentPath, properties, elementName);
+ destination.create(currentPath, properties);
}
/**
@@ -390,7 +390,7 @@
/**
* Create a property with the given name and value, obtained from an attribute name
and value in the XML content.
* <p>
- * By default, this method creates a property by directly using the value as the sole
String value of the property.
+ * By default, this method creates a property by directly using the value as the sole
value of the property.
* </p>
*
* @param propertyName the name of the property; never null
@@ -398,9 +398,10 @@
* @return the property; may not be null
*/
protected Property createProperty( Name propertyName,
- String value ) {
+ Object value ) {
propertyValues[0] = value;
- return propertyFactory.create(propertyName, propertyValues);
+ Property result = propertyFactory.create(propertyName, propertyValues);
+ return result;
}
/**
@@ -424,14 +425,22 @@
*
* @param path the absolute path of the node
* @param properties the properties for the node; never null, but may be empty if
there are no properties
- * @param elementName the name of the XML element from which the node should be
created; never null, and may or may not be
- * the same name as the last segment of the path
*/
public void create( Path path,
- List<Property> properties,
- Name elementName );
+ List<Property> properties );
/**
+ * Create a node at the supplied path and with the supplied attributes. The path
will be absolute.
+ *
+ * @param path the absolute path of the node
+ * @param firstProperty the first property
+ * @param additionalProperties the remaining properties for the node
+ */
+ public void create( Path path,
+ Property firstProperty,
+ Property... additionalProperties );
+
+ /**
* Signal to this destination that any enqueued create requests should be
submitted. Usually this happens at the end of
* the document parsing, but an implementer must allow for it to be called
multiple times and anytime during parsing.
*/
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerContext.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerContext.java 2008-11-10
23:57:53 UTC (rev 618)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerContext.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -29,15 +29,15 @@
import org.jboss.dna.common.collection.Problems;
import org.jboss.dna.common.collection.SimpleProblems;
import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.graph.BasicExecutionContext;
import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.NamespaceRegistry;
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.PropertyFactory;
import org.jboss.dna.graph.properties.ValueFactories;
-import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
-import org.jboss.dna.graph.properties.basic.StandardValueFactories;
/**
* @author John Verhaeg
@@ -45,18 +45,17 @@
@Immutable
public class MockSequencerContext implements SequencerContext {
- private final ValueFactories factories;
- private final NamespaceRegistry registry = new BasicNamespaceRegistry();
+ private final ExecutionContext context = new BasicExecutionContext();
private final Problems problems = new SimpleProblems();
public MockSequencerContext() {
+ NamespaceRegistry registry = context.getNamespaceRegistry();
registry.register("jcr", "http://www.jcp.org/jcr/1.0");
registry.register("mix", "http://www.jcp.org/jcr/mix/1.0");
registry.register("nt", "http://www.jcp.org/jcr/nt/1.0");
registry.register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
registry.register("dnadtd",
"http://www.jboss.org/dna/dtd/1.0");
registry.register("dnaxml",
"http://www.jboss.org/dna/xml/1.0");
- factories = new StandardValueFactories(registry);
}
/**
@@ -65,7 +64,7 @@
* @see
org.jboss.dna.common.component.ClassLoaderFactory#getClassLoader(java.lang.String[])
*/
public ClassLoader getClassLoader( String... classpath ) {
- return null;
+ return context.getClassLoader(classpath);
}
/**
@@ -119,7 +118,7 @@
* @see org.jboss.dna.graph.ExecutionContext#getAccessControlContext()
*/
public AccessControlContext getAccessControlContext() {
- return null;
+ return context.getAccessControlContext();
}
/**
@@ -128,7 +127,7 @@
* @see org.jboss.dna.graph.ExecutionContext#getLogger(java.lang.Class)
*/
public Logger getLogger( Class<?> clazz ) {
- return null;
+ return context.getLogger(clazz);
}
/**
@@ -137,7 +136,7 @@
* @see org.jboss.dna.graph.ExecutionContext#getLogger(java.lang.String)
*/
public Logger getLogger( String name ) {
- return null;
+ return context.getLogger(name);
}
/**
@@ -146,7 +145,7 @@
* @see org.jboss.dna.graph.ExecutionContext#getLoginContext()
*/
public LoginContext getLoginContext() {
- return null;
+ return context.getLoginContext();
}
/**
@@ -155,7 +154,7 @@
* @see org.jboss.dna.graph.ExecutionContext#getNamespaceRegistry()
*/
public NamespaceRegistry getNamespaceRegistry() {
- return registry;
+ return context.getNamespaceRegistry();
}
/**
@@ -164,7 +163,7 @@
* @see org.jboss.dna.graph.ExecutionContext#getPropertyFactory()
*/
public PropertyFactory getPropertyFactory() {
- return null;
+ return context.getPropertyFactory();
}
/**
@@ -173,7 +172,7 @@
* @see org.jboss.dna.graph.ExecutionContext#getSubject()
*/
public Subject getSubject() {
- return null;
+ return context.getSubject();
}
/**
@@ -182,6 +181,6 @@
* @see org.jboss.dna.graph.ExecutionContext#getValueFactories()
*/
public ValueFactories getValueFactories() {
- return factories;
+ return context.getValueFactories();
}
}
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerOutput.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerOutput.java 2008-11-10
23:57:53 UTC (rev 618)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/sequencers/MockSequencerOutput.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -21,12 +21,15 @@
*/
package org.jboss.dna.graph.sequencers;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.Map;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.properties.Property;
/**
* @author Randall Hauch
@@ -35,12 +38,19 @@
@NotThreadSafe
public class MockSequencerOutput implements SequencerOutput {
- private final Map<Path, Object[]> properties;
+ private final Map<Path, Map<Name, Property>> propertiesByPath;
private final SequencerContext context;
+ private final LinkedList<Path> nodePathsInCreationOrder;
public MockSequencerOutput( SequencerContext context ) {
+ this(context, false);
+ }
+
+ public MockSequencerOutput( SequencerContext context,
+ boolean recordOrderOfNodeCreation ) {
this.context = context;
- this.properties = new HashMap<Path, Object[]>();
+ this.propertiesByPath = new HashMap<Path, Map<Name, Property>>();
+ this.nodePathsInCreationOrder = recordOrderOfNodeCreation ? new
LinkedList<Path>() : null;
}
/**
@@ -49,11 +59,24 @@
public void setProperty( Path nodePath,
Name propertyName,
Object... values ) {
- Path key = createKey(nodePath, propertyName);
+ Map<Name, Property> properties = propertiesByPath.get(nodePath);
if (values == null || values.length == 0) {
- this.properties.remove(key);
+ // remove the property ...
+ if (properties != null) {
+ properties.remove(propertyName);
+ if (properties.isEmpty()) {
+ propertiesByPath.remove(nodePath);
+ if (nodePathsInCreationOrder != null)
nodePathsInCreationOrder.remove(nodePath);
+ }
+ }
} else {
- this.properties.put(key, values);
+ if (properties == null) {
+ properties = new HashMap<Name, Property>();
+ propertiesByPath.put(nodePath, properties);
+ if (nodePathsInCreationOrder != null)
nodePathsInCreationOrder.add(nodePath);
+ }
+ Property property = context.getPropertyFactory().create(propertyName,
values);
+ properties.put(propertyName, property);
}
}
@@ -88,32 +111,57 @@
setProperty(path, name, values);
}
- public Object[] getPropertyValues( String nodePath,
- String property ) {
- Path key = createKey(nodePath, property);
- return this.properties.get(key);
+ public LinkedList<Path> getOrderOfCreation() {
+ return nodePathsInCreationOrder;
}
- public boolean hasProperty( String nodePath,
- String property ) {
- Path key = createKey(nodePath, property);
- return this.properties.containsKey(key);
+ public boolean exists( Path nodePath ) {
+ return this.propertiesByPath.containsKey(nodePath);
}
- public boolean hasProperties() {
- return this.properties.size() > 0;
+ public Map<Name, Property> getProperties( Path nodePath ) {
+ Map<Name, Property> properties = this.propertiesByPath.get(nodePath);
+ if (properties == null) return null;
+ return Collections.unmodifiableMap(properties);
}
- protected Path createKey( String nodePath,
- String propertyName ) {
+ public Property getProperty( String nodePath,
+ String propertyName ) {
Path path = context.getValueFactories().getPathFactory().create(nodePath);
Name name = context.getValueFactories().getNameFactory().create(propertyName);
- return createKey(path, name);
+ return getProperty(path, name);
}
- protected Path createKey( Path nodePath,
- Name propertyName ) {
- return context.getValueFactories().getPathFactory().create(nodePath,
propertyName);
+ public Property getProperty( Path nodePath,
+ Name propertyName ) {
+ Map<Name, Property> properties = this.propertiesByPath.get(nodePath);
+ if (properties == null) return null;
+ return properties.get(propertyName);
}
+ public Object[] getPropertyValues( String nodePath,
+ String propertyName ) {
+ Path path = context.getValueFactories().getPathFactory().create(nodePath);
+ return getPropertyValues(path, propertyName);
+ }
+
+ public Object[] getPropertyValues( Path path,
+ String propertyName ) {
+ Name name = context.getValueFactories().getNameFactory().create(propertyName);
+ Property prop = getProperty(path, name);
+ if (prop != null) {
+ return prop.getValuesAsArray();
+ }
+ return null;
+ }
+
+ public boolean hasProperty( String nodePath,
+ String property ) {
+ return getProperty(nodePath, property) != null;
+ }
+
+ public boolean hasProperties() {
+ return this.propertiesByPath.size() > 0;
+ }
+
}
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java 2008-11-10
23:57:53 UTC (rev 618)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -29,6 +29,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -432,11 +433,44 @@
private final LinkedList<CreateNodeRequest> requests = new
LinkedList<CreateNodeRequest>();
public void create( Path path,
- List<Property> properties,
- Name elementName ) {
+ List<Property> properties ) {
requests.add(new CreateNodeRequest(new Location(path), properties));
}
+ public void create( final Path path,
+ final Property firstProperty,
+ final Property... additionalProperties ) {
+ Location location = new Location(path);
+ if (firstProperty == null) {
+ requests.add(new CreateNodeRequest(location));
+ } else {
+ if (additionalProperties == null || additionalProperties.length == 0) {
+ requests.add(new CreateNodeRequest(location, firstProperty));
+ } else {
+ Iterator<Property> iter = new Iterator<Property>() {
+ private int index = -1;
+
+ public boolean hasNext() {
+ return index < additionalProperties.length;
+ }
+
+ public Property next() {
+ if (index == -1) {
+ ++index;
+ return firstProperty;
+ }
+ return additionalProperties[index++];
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ requests.add(new CreateNodeRequest(location, iter));
+ }
+ }
+ }
+
@SuppressWarnings( "synthetic-access" )
public ExecutionContext getExecutionContext() {
return XmlHandlerTest.this.context;
Added:
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencer.java
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencer.java
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencer.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+/**
+ * An XML sequencer that is a specialization of {@link XmlSequencer} by inheriting
unqualified attribute namespaces
+ * {@link XmlSequencer.AttributeScoping#INHERIT_ELEMENT_NAMESPACE from the element}
rather than from the
+ * {@link XmlSequencer.AttributeScoping#USE_DEFAULT_NAMESPACE default namespace}.
+ *
+ * @author Randall Hauch
+ */
+public class InheritingXmlSequencer extends XmlSequencer {
+
+ public InheritingXmlSequencer() {
+ setAttributeScoping(AttributeScoping.INHERIT_ELEMENT_NAMESPACE);
+ }
+
+}
Property changes on:
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencer.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java 2008-11-10
23:57:53 UTC (rev 618)
+++
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencer.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -22,42 +22,64 @@
package org.jboss.dna.sequencer.xml;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import org.jboss.dna.common.util.StringUtil;
-import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.JcrNtLexicon;
import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
-import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.sequencers.SequencerContext;
import org.jboss.dna.graph.sequencers.SequencerOutput;
import org.jboss.dna.graph.sequencers.StreamSequencer;
-import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
-import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
-import org.xml.sax.ext.DefaultHandler2;
import org.xml.sax.helpers.XMLReaderFactory;
/**
+ * A sequencer for XML files, which maintains DTD, entity, comments, and other content.
Note that by default the sequencer uses
+ * the {@link XmlSequencer.AttributeScoping#USE_DEFAULT_NAMESPACE default namespace} for
unqualified attribute rather than
+ * {@link XmlSequencer.AttributeScoping#INHERIT_ELEMENT_NAMESPACE inheriting the
namespace from the element}. (See also
+ * {@link InheritingXmlSequencer}.
+ *
* @author John Verhaeg
*/
public class XmlSequencer implements StreamSequencer {
- private static final String DEFAULT_PRIMARY_TYPE = "nt:unstructured";
- private static final String DECL_HANDLER_FEATURE =
"http://xml.org/sax/properties/declaration-handler";
- private static final String ENTITY_RESOLVER_2_FEATURE =
"http://xml.org/sax/features/use-entity-resolver2";
- private static final String LEXICAL_HANDLER_FEATURE =
"http://xml.org/sax/properties/lexical-handler";
- private static final String RESOLVE_DTD_URIS_FEATURE =
"http://xml.org/sax/features/resolve-dtd-uris";
- private static final String LOAD_EXTERNAL_DTDS_FEATURE =
"http://apache.org/xml/features/nonvalidating/load-external-dtd";
+ /**
+ * The choices for how attributes that have no namespace prefix should be assigned a
namespace.
+ *
+ * @author Randall Hauch
+ */
+ public enum AttributeScoping {
+ /** The attribute's namespace is the default namespace */
+ USE_DEFAULT_NAMESPACE,
+ /** The attribute's namespace is the same namespace as the containing element
*/
+ INHERIT_ELEMENT_NAMESPACE;
+ }
+ /*package*/static final String DEFAULT_PRIMARY_TYPE = "nt:unstructured";
+ /*package*/static final String DECL_HANDLER_FEATURE =
"http://xml.org/sax/properties/declaration-handler";
+ /*package*/static final String ENTITY_RESOLVER_2_FEATURE =
"http://xml.org/sax/features/use-entity-resolver2";
+ /*package*/static final String LEXICAL_HANDLER_FEATURE =
"http://xml.org/sax/properties/lexical-handler";
+ /*package*/static final String RESOLVE_DTD_URIS_FEATURE =
"http://xml.org/sax/features/resolve-dtd-uris";
+ /*package*/static final String LOAD_EXTERNAL_DTDS_FEATURE =
"http://apache.org/xml/features/nonvalidating/load-external-dtd";
+
+ private AttributeScoping scoping = AttributeScoping.USE_DEFAULT_NAMESPACE;
+
/**
+ * @param scoping Sets scoping to the specified value.
+ */
+ public void setAttributeScoping( AttributeScoping scoping ) {
+ this.scoping = scoping;
+ }
+
+ /**
+ * @return scoping
+ */
+ public AttributeScoping getAttributeScoping() {
+ return scoping;
+ }
+
+ /**
* {@inheritDoc}
*
* @see org.jboss.dna.graph.sequencers.StreamSequencer#sequence(InputStream,
SequencerOutput, SequencerContext)
@@ -67,8 +89,13 @@
SequencerContext context ) {
XMLReader reader;
try {
+ // Set up the XML handler ...
+ Name primaryType = JcrNtLexicon.UNSTRUCTURED;
+ Name nameAttribute = null;
+ TextDecoder decoder = null;
+ XmlSequencerHandler handler = new XmlSequencerHandler(output, context,
nameAttribute, primaryType, decoder, scoping);
+ // Create the reader ...
reader = XMLReaderFactory.createXMLReader();
- Handler handler = new Handler(output, context);
reader.setContentHandler(handler);
reader.setErrorHandler(handler);
// Ensure handler acting as entity resolver 2
@@ -97,9 +124,9 @@
* @param featureName the name of the feature; may not be null
* @param value the value for the feature
*/
- private void setFeature( XMLReader reader,
- String featureName,
- boolean value ) {
+ /*package*/static void setFeature( XMLReader reader,
+ String featureName,
+ boolean value ) {
try {
if (reader.getFeature(featureName) != value) {
reader.setFeature(featureName, value);
@@ -109,428 +136,4 @@
}
}
- private final class Handler extends DefaultHandler2 {
-
- private final SequencerOutput output;
- private final SequencerContext context;
-
- private Path path; // The DNA path of the node representing the current XML
element
-
- // Cached instances of the name factory and commonly referenced names
- private final NameFactory nameFactory;
- private Name defaultPrimaryType;
-
- // Recursive map used to track the number of occurrences of names for elements
under a particular path
- private Map<Name, List<IndexedName>> nameToIndexedNamesMap = new
HashMap<Name, List<IndexedName>>();
-
- // The stack of recursive maps being processed, with the head entry being the map
for the current path
- private final LinkedList<Map<Name, List<IndexedName>>>
nameToIndexedNamesMapStack = new LinkedList<Map<Name,
List<IndexedName>>>();
-
- // The stack of XML namespace in scope, with the head entry being namespace of
the closest ancestor element declaring a
- // namespace.
- private final LinkedList<String> nsStack = new LinkedList<String>();
-
- // Builder used to concatenate concurrent lines of CDATA into a single value.
- private StringBuilder cDataBuilder;
-
- // Builder used to concatenate concurrent lines of element content and entity
evaluations into a single value.
- private StringBuilder contentBuilder;
-
- // The entity being processed
- private String entity;
-
- Handler( SequencerOutput output,
- SequencerContext context ) {
- assert output != null;
- assert context != null;
- this.output = output;
- this.context = context;
- // Initialize path to a an empty path relative to the SequencerOutput's
target path.
- path = context.getValueFactories().getPathFactory().createRelativePath();
- // Cache name factory since it is frequently used
- nameFactory = context.getValueFactories().getNameFactory();
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
- */
- @Override
- public void characters( char[] ch,
- int start,
- int length ) {
- String content = String.valueOf(ch, start, length);
- // Check if data should be appended to previously parsed CDATA
- if (cDataBuilder == null) {
- // If content is for an entity, replace with entity reference
- if (entity != null) {
- content = '&' + entity + ';';
- }
- // Check if first line of content
- if (contentBuilder == null) {
- contentBuilder = new StringBuilder(content);
- } else {
- // Append additional lines or entity evaluations to previous content,
separated by a space
- if (entity == null) {
- contentBuilder.append(' ');
- }
- contentBuilder.append(content);
- // Text within builder will be output when another element or CDATA
is encountered
- }
- } else {
- cDataBuilder.append(ch, start, length);
- // Text within builder will be output at the end of CDATA
- }
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.ext.DefaultHandler2#comment(char[], int, int)
- */
- @Override
- public void comment( char[] ch,
- int start,
- int length ) {
- // Output separate nodes for each comment since multiple are allowed
- startElement(DnaXmlLexicon.COMMENT);
- output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.COMMENT);
- output.setProperty(path, DnaXmlLexicon.COMMENT_CONTENT, String.valueOf(ch,
start, length));
- endElement();
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.ext.DefaultHandler2#endCDATA()
- */
- @Override
- public void endCDATA() {
- // Output CDATA built in characters() method
- output.setProperty(path, DnaXmlLexicon.CDATA_CONTENT,
cDataBuilder.toString());
- endElement();
- // Null-out builder to free memory
- cDataBuilder = null;
- }
-
- private void endContent() {
- if (contentBuilder != null) {
- // Normalize content
- String content = StringUtil.normalize(contentBuilder.toString());
- // Null-out builder to setup for subsequent content.
- // Must be done before call to startElement below to prevent infinite
loop.
- contentBuilder = null;
- // Skip if nothing in content but whitespace
- if (content.length() > 0) {
- // Create separate node for each content entry since entries can be
interspersed amongst child elements
- startElement(DnaXmlLexicon.ELEMENT_CONTENT);
- output.setProperty(path, JcrLexicon.PRIMARY_TYPE,
DnaXmlLexicon.ELEMENT_CONTENT);
- output.setProperty(path, DnaXmlLexicon.ELEMENT_CONTENT, content);
- endElement();
- }
- }
- }
-
- private void endElement() {
- // Recover parent's path, namespace, and indexedName map, clearing the
ended element's map to free memory
- path = path.getParent();
- nameToIndexedNamesMap.clear();
- nameToIndexedNamesMap = nameToIndexedNamesMapStack.removeFirst();
- nsStack.removeFirst();
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
java.lang.String, java.lang.String)
- */
- @Override
- public void endElement( String uri,
- String localName,
- String name ) {
- // Check if content still needs to be output
- endContent();
- endElement();
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.ext.DefaultHandler2#endEntity(java.lang.String)
- */
- @Override
- public void endEntity( String name ) {
- entity = null;
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
- */
- @Override
- public void error( SAXParseException error ) {
- context.getLogger(XmlSequencer.class).error(error,
XmlSequencerI18n.errorSequencingXmlDocument, error);
- context.getProblems().addError(error,
XmlSequencerI18n.errorSequencingXmlDocument, error);
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.ext.DefaultHandler2#externalEntityDecl(java.lang.String,
java.lang.String, java.lang.String)
- */
- @Override
- public void externalEntityDecl( String name,
- String publicId,
- String systemId ) {
- // Add "synthetic" entity container to path to help prevent name
collisions with XML elements
- Name entityName = DnaDtdLexicon.ENTITY;
- startElement(entityName);
- output.setProperty(path, JcrLexicon.PRIMARY_TYPE, entityName);
- output.setProperty(path, nameFactory.create(DnaDtdLexicon.NAME), name);
- output.setProperty(path, nameFactory.create(DnaDtdLexicon.PUBLIC_ID),
publicId);
- output.setProperty(path, nameFactory.create(DnaDtdLexicon.SYSTEM_ID),
systemId);
- endElement();
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see
org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException)
- */
- @Override
- public void fatalError( SAXParseException error ) {
- context.getLogger(XmlSequencer.class).error(error,
XmlSequencerI18n.fatalErrorSequencingXmlDocument, error);
- context.getProblems().addError(error,
XmlSequencerI18n.fatalErrorSequencingXmlDocument, error);
- }
-
- private Name getDefaultPrimaryType() {
- if (defaultPrimaryType == null) {
- defaultPrimaryType = nameFactory.create(DEFAULT_PRIMARY_TYPE);
- }
- return defaultPrimaryType;
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.ext.DefaultHandler2#internalEntityDecl(java.lang.String,
java.lang.String)
- */
- @Override
- public void internalEntityDecl( String name,
- String value ) {
- // Add "synthetic" entity container to path to help prevent name
collisions with XML elements
- Name entityName = DnaDtdLexicon.ENTITY;
- startElement(entityName);
- output.setProperty(path, JcrLexicon.PRIMARY_TYPE, entityName);
- output.setProperty(path, DnaDtdLexicon.NAME, name);
- output.setProperty(path, DnaDtdLexicon.VALUE, value);
- endElement();
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see
org.xml.sax.helpers.DefaultHandler#processingInstruction(java.lang.String,
java.lang.String)
- */
- @Override
- public void processingInstruction( String target,
- String data ) {
- // Output separate nodes for each instruction since multiple are allowed
- Name name = DnaXmlLexicon.PROCESSING_INSTRUCTION;
- startElement(name);
- output.setProperty(path, JcrLexicon.PRIMARY_TYPE, name);
- output.setProperty(path, DnaXmlLexicon.TARGET, target);
- output.setProperty(path, DnaXmlLexicon.PROCESSING_INSTRUCTION_CONTENT,
data);
- endElement();
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.ext.DefaultHandler2#startCDATA()
- */
- @Override
- public void startCDATA() {
- // Output separate nodes for each CDATA since multiple are allowed
- startElement(DnaXmlLexicon.CDATA);
- // Prepare builder for concatenating consecutive lines of CDATA
- cDataBuilder = new StringBuilder();
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.helpers.DefaultHandler#startDocument()
- */
- @Override
- public void startDocument() {
- output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.DOCUMENT);
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.ext.DefaultHandler2#startDTD(java.lang.String,
java.lang.String, java.lang.String)
- */
- @Override
- public void startDTD( String name,
- String publicId,
- String systemId ) {
- output.setProperty(path, DnaDtdLexicon.NAME, name);
- output.setProperty(path, DnaDtdLexicon.PUBLIC_ID, publicId);
- output.setProperty(path, DnaDtdLexicon.SYSTEM_ID, systemId);
- }
-
- private void startElement( Name name ) {
- // Check if content still needs to be output
- endContent();
- // Add name to list of indexed names for this element to ensure we use the
correct index (which is the size of the
- // list)
- List<IndexedName> indexedNames = nameToIndexedNamesMap.get(name);
- if (indexedNames == null) {
- indexedNames = new ArrayList<IndexedName>();
- nameToIndexedNamesMap.put(name, indexedNames);
- }
- IndexedName indexedName = new IndexedName();
- indexedNames.add(indexedName);
- // Add element name and the appropriate index to the path.
- // Per the JCR spec, the index must be relative to same-name sibling nodes
- path = context.getValueFactories().getPathFactory().create(path, name,
indexedNames.size());
- path = path.getNormalizedPath();
- // Add the indexed name map to the stack and set the current map to the new
element's map
- nameToIndexedNamesMapStack.addFirst(nameToIndexedNamesMap);
- nameToIndexedNamesMap = indexedName.nameToIndexedNamesMap;
- // Set the current namespace to whatever is declared by this element, or if
not declared, to its nearest ancestor that
- // does declare a namespace.
- String ns = name.getNamespaceUri();
- if (ns.length() == 0) {
- nsStack.addFirst(nsStack.isEmpty() ? "" : nsStack.getFirst());
- } else {
- nsStack.addFirst(ns);
- }
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
java.lang.String, java.lang.String,
- * org.xml.sax.Attributes)
- */
- @Override
- public void startElement( String uri,
- String localName,
- String name,
- Attributes attributes ) {
- // Look for the "jcr:name" attribute, and use that if it's
there
- Name type = getDefaultPrimaryType();
- Name nameObj = nameFactory.create(name);
- for (int ndx = 0, len = attributes.getLength(); ndx < len; ++ndx) {
- String ns = attributes.getURI(ndx);
- String attrLocalName = attributes.getLocalName(ndx);
- Object value = attributes.getValue(ndx);
- String jcrNsUri =
context.getNamespaceRegistry().getNamespaceForPrefix("jcr");
- if (jcrNsUri != null && jcrNsUri.equals(ns) &&
attrLocalName.equals("name")) {
- nameObj = nameFactory.create(value);
- break;
- }
- }
- startElement(nameObj);
- output.setProperty(path, JcrLexicon.PRIMARY_TYPE, type);
- // Output this element's attributes using the attribute's namespace,
if supplied, or the current namespace in scope.
- String inheritedNs = nsStack.getFirst();
- for (int ndx = 0, len = attributes.getLength(); ndx < len; ++ndx) {
- String ns = attributes.getURI(ndx);
- String attrLocalName = attributes.getLocalName(ndx);
- Object value = attributes.getValue(ndx);
- String jcrNsUri =
context.getNamespaceRegistry().getNamespaceForPrefix("jcr");
- if (jcrNsUri != null && jcrNsUri.equals(ns) &&
attrLocalName.equals("primaryType")) {
- value = nameFactory.create(value);
- }
- if (jcrNsUri != null && jcrNsUri.equals(ns) &&
attrLocalName.equals("name")) {
- continue;
- }
- output.setProperty(path, nameFactory.create(ns.length() == 0 ?
inheritedNs : ns, attrLocalName), value);
- }
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.ext.DefaultHandler2#startEntity(java.lang.String)
- */
- @Override
- public void startEntity( String name ) {
- entity = name;
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see org.xml.sax.helpers.DefaultHandler#startPrefixMapping(java.lang.String,
java.lang.String)
- */
- @Override
- public void startPrefixMapping( String prefix,
- String uri ) {
- // Register any unregistered namespaces
- NamespaceRegistry registry = context.getNamespaceRegistry();
- if (!registry.isRegisteredNamespaceUri(uri)) {
- registry.register(prefix, uri);
- }
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see
org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException)
- */
- @Override
- public void warning( SAXParseException warning ) {
- context.getLogger(XmlSequencer.class).warn(warning,
XmlSequencerI18n.warningSequencingXmlDocument);
- context.getProblems().addWarning(warning,
XmlSequencerI18n.warningSequencingXmlDocument, warning);
- }
- }
-
- private class IndexedName {
-
- Map<Name, List<IndexedName>> nameToIndexedNamesMap = new
HashMap<Name, List<IndexedName>>();
-
- IndexedName() {
- }
- }
}
Added:
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,604 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.text.XmlNameEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.BasicExecutionContext;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.NameFactory;
+import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.properties.PropertyFactory;
+import org.jboss.dna.graph.properties.ValueFormatException;
+import org.jboss.dna.graph.properties.basic.LocalNamespaceRegistry;
+import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.jboss.dna.graph.sequencers.SequencerOutput;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ext.DefaultHandler2;
+
+/**
+ * @author Randall Hauch
+ */
+public class XmlSequencerHandler extends DefaultHandler2 {
+
+ private final SequencerOutput output;
+ private final SequencerContext context;
+
+ /**
+ * Decoder for XML names, to turn '_xHHHH_' sequences in the XML element and
attribute names into the corresponding UTF-16
+ * characters.
+ */
+ public static TextDecoder DEFAULT_DECODER = new XmlNameEncoder();
+
+ /**
+ * The default {@link XmlSequencer.AttributeScoping}.
+ */
+ public static XmlSequencer.AttributeScoping DEFAULT_ATTRIBUTE_SCOPING =
XmlSequencer.AttributeScoping.USE_DEFAULT_NAMESPACE;
+
+ /**
+ * The name of the attribute that should be used for the node name.
+ */
+ protected final Name nameAttribute;
+
+ /**
+ * The default primary type.
+ */
+ protected final Name defaultPrimaryType;
+
+ /**
+ * The cached reference to the graph's path factory.
+ */
+ protected final PathFactory pathFactory;
+
+ /**
+ * The cached reference to the graph's name factory.
+ */
+ protected final NameFactory nameFactory;
+
+ /**
+ * The cached reference to the graph's property factory.
+ */
+ protected final PropertyFactory propertyFactory;
+
+ /**
+ * The cached reference to the graph's namespace registry.
+ */
+ protected final NamespaceRegistry namespaceRegistry;
+
+ /**
+ * The TextDecoder that is used to decode the names.
+ */
+ protected final TextDecoder decoder;
+
+ /**
+ * The stack of prefixes for each namespace, which is used to keep the {@link
#namespaceRegistry local namespace registry} in
+ * sync with the namespaces in the XML document.
+ */
+ private final Map<String, LinkedList<String>> prefixStackByUri = new
HashMap<String, LinkedList<String>>();
+
+ private final XmlSequencer.AttributeScoping attributeScoping;
+
+ /**
+ * The path for the node representing the current element. This starts out as the
path supplied by the constructor, and never
+ * is shorter than that initial path.
+ */
+ protected Path currentPath;
+
+ // Recursive map used to track the number of occurrences of names for elements under
a particular path
+ private Map<Name, List<IndexedName>> nameToIndexedNamesMap = new
HashMap<Name, List<IndexedName>>();
+
+ // The stack of recursive maps being processed, with the head entry being the map for
the current path
+ private final LinkedList<Map<Name, List<IndexedName>>>
nameToIndexedNamesMapStack = new LinkedList<Map<Name,
List<IndexedName>>>();
+
+ private String currentEntityName;
+ private StringBuilder cDataContent;
+ private StringBuilder contentBuilder;
+ private final Problems problems;
+
+ /**
+ * @param output
+ * @param context
+ * @param nameAttribute
+ * @param defaultPrimaryType
+ * @param textDecoder
+ * @param scoping
+ */
+ XmlSequencerHandler( SequencerOutput output,
+ SequencerContext context,
+ Name nameAttribute,
+ Name defaultPrimaryType,
+ TextDecoder textDecoder,
+ XmlSequencer.AttributeScoping scoping ) {
+ CheckArg.isNotNull(output, "output");
+ CheckArg.isNotNull(context, "context");
+
+ // Use the execution context ...
+ this.output = output;
+ this.context = context;
+ this.problems = context.getProblems();
+ assert this.problems != null;
+
+ this.nameAttribute = nameAttribute;
+ this.defaultPrimaryType = defaultPrimaryType;
+ this.decoder = textDecoder != null ? textDecoder : DEFAULT_DECODER;
+ this.attributeScoping = scoping != null ? scoping : DEFAULT_ATTRIBUTE_SCOPING;
+
+ // Set up a local namespace registry that is kept in sync with the namespaces
found in this XML document ...
+ NamespaceRegistry namespaceRegistry = new
LocalNamespaceRegistry(this.context.getNamespaceRegistry());
+ final ExecutionContext localContext = new BasicExecutionContext(this.context,
namespaceRegistry);
+
+ // Set up references to frequently-used objects in the context ...
+ this.nameFactory = localContext.getValueFactories().getNameFactory();
+ this.pathFactory = localContext.getValueFactories().getPathFactory();
+ this.propertyFactory = localContext.getPropertyFactory();
+ this.namespaceRegistry = localContext.getNamespaceRegistry();
+ assert this.nameFactory != null;
+ assert this.pathFactory != null;
+ assert this.propertyFactory != null;
+ assert this.namespaceRegistry != null;
+
+ // Set up the initial path ...
+ this.currentPath = this.pathFactory.createRelativePath();
+ assert this.currentPath != null;
+ }
+
+ private void startNode( Name name ) {
+ // Check if content still needs to be output
+ if (contentBuilder != null) endContent();
+ // Add name to list of indexed names for this element to ensure we use the
correct index (which is the size of the
+ // list)
+ List<IndexedName> indexedNames = nameToIndexedNamesMap.get(name);
+ if (indexedNames == null) {
+ indexedNames = new ArrayList<IndexedName>();
+ nameToIndexedNamesMap.put(name, indexedNames);
+ }
+ IndexedName indexedName = new IndexedName();
+ indexedNames.add(indexedName);
+ // Add element name and the appropriate index to the path.
+ // Per the JCR spec, the index must be relative to same-name sibling nodes
+ currentPath = pathFactory.create(currentPath, name,
indexedNames.size()).getNormalizedPath();
+ // currentPath = currentPath.getNormalizedPath();
+ // Add the indexed name map to the stack and set the current map to the new
element's map
+ nameToIndexedNamesMapStack.addFirst(nameToIndexedNamesMap);
+ nameToIndexedNamesMap = indexedName.nameToIndexedNamesMap;
+ }
+
+ private void endNode() {
+ // Recover parent's path, namespace, and indexedName map, clearing the ended
element's map to free memory
+ currentPath = currentPath.getParent();
+ currentPath = currentPath.getNormalizedPath();
+ nameToIndexedNamesMap.clear();
+ nameToIndexedNamesMap = nameToIndexedNamesMapStack.removeFirst();
+ }
+
+ /**
+ * See if there is any element content that needs to be completed.
+ */
+ protected void endContent() {
+ // Process the content of the element ...
+ String content = StringUtil.normalize(contentBuilder.toString());
+ // Null-out builder to setup for subsequent content.
+ // Must be done before call to startElement below to prevent infinite loop.
+ contentBuilder = null;
+ // Skip if nothing in content but whitespace
+ if (content.length() > 0) {
+ // Create separate node for each content entry since entries can be
interspersed amongst child elements
+ startNode(DnaXmlLexicon.ELEMENT_CONTENT);
+ output.setProperty(currentPath, JcrLexicon.PRIMARY_TYPE,
DnaXmlLexicon.ELEMENT_CONTENT);
+ output.setProperty(currentPath, DnaXmlLexicon.ELEMENT_CONTENT, content);
+ endNode();
+ }
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startDocument()
+ */
+ @Override
+ public void startDocument() {
+ output.setProperty(currentPath, JcrLexicon.PRIMARY_TYPE,
DnaXmlLexicon.DOCUMENT);
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#startDTD(java.lang.String, java.lang.String,
java.lang.String)
+ */
+ @Override
+ public void startDTD( String name,
+ String publicId,
+ String systemId ) {
+ output.setProperty(currentPath, DnaDtdLexicon.NAME, name);
+ output.setProperty(currentPath, DnaDtdLexicon.PUBLIC_ID, publicId);
+ output.setProperty(currentPath, DnaDtdLexicon.SYSTEM_ID, systemId);
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#externalEntityDecl(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ @Override
+ public void externalEntityDecl( String name,
+ String publicId,
+ String systemId ) {
+ // Add "synthetic" entity container to path to help prevent name
collisions with XML elements
+ startNode(DnaDtdLexicon.ENTITY);
+ output.setProperty(currentPath, JcrLexicon.PRIMARY_TYPE, DnaDtdLexicon.ENTITY);
+ output.setProperty(currentPath, DnaDtdLexicon.NAME, name);
+ if (publicId != null) output.setProperty(currentPath, DnaDtdLexicon.PUBLIC_ID,
publicId);
+ if (systemId != null) output.setProperty(currentPath, DnaDtdLexicon.SYSTEM_ID,
systemId);
+ endNode();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#internalEntityDecl(java.lang.String,
java.lang.String)
+ */
+ @Override
+ public void internalEntityDecl( String name,
+ String value ) {
+ // Add "synthetic" entity container to path to help prevent name
collisions with XML elements
+ startNode(DnaDtdLexicon.ENTITY);
+ output.setProperty(currentPath, JcrLexicon.PRIMARY_TYPE, DnaDtdLexicon.ENTITY);
+ output.setProperty(currentPath, DnaDtdLexicon.NAME, name);
+ output.setProperty(currentPath, DnaDtdLexicon.VALUE, value);
+ endNode();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#processingInstruction(java.lang.String,
java.lang.String)
+ */
+ @Override
+ public void processingInstruction( String target,
+ String data ) {
+ // Output separate nodes for each instruction since multiple are allowed
+ startNode(DnaXmlLexicon.PROCESSING_INSTRUCTION);
+ output.setProperty(currentPath, JcrLexicon.PRIMARY_TYPE,
DnaXmlLexicon.PROCESSING_INSTRUCTION);
+ output.setProperty(currentPath, DnaXmlLexicon.TARGET, target.trim());
+ if (data != null) {
+ output.setProperty(currentPath, DnaXmlLexicon.PROCESSING_INSTRUCTION_CONTENT,
data.trim());
+ }
+ endNode();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This method ensures that the namespace is registered with the {@link
NamespaceRegistry registry}, using the supplied prefix
+ * to register the namespace if required. Note that because this class does not
really use the namespace prefixes to create
+ * {@link Name} objects, no attempt is made to match the XML namespace prefixes.
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startPrefixMapping(java.lang.String,
java.lang.String)
+ */
+ @Override
+ public void startPrefixMapping( String prefix,
+ String uri ) {
+ assert uri != null;
+ // Add the prefix to the stack ...
+ LinkedList<String> prefixStack = this.prefixStackByUri.get(uri);
+ if (prefixStack == null) {
+ prefixStack = new LinkedList<String>();
+ this.prefixStackByUri.put(uri, prefixStack);
+ }
+ prefixStack.addFirst(prefix);
+
+ // If the namespace is already registered, then we'll have to register it in
the context's registry, too.
+ if (!namespaceRegistry.isRegisteredNamespaceUri(uri)) {
+ // The namespace is not already registered (locally or in the context's
registry), so we have to
+ // register it with the context's registry (which the local register then
inherits).
+ NamespaceRegistry contextRegistry = context.getNamespaceRegistry();
+ if (contextRegistry.getNamespaceForPrefix(prefix) != null) {
+ // The prefix is already bound, so register and generate a unique prefix
+ context.getNamespaceRegistry().getPrefixForNamespaceUri(uri, true);
+ // Now register locally with the supplied prefix ...
+ namespaceRegistry.register(prefix, uri);
+ } else {
+ context.getNamespaceRegistry().register(prefix, uri);
+ }
+ } else {
+ // It is already registered, but re-register it locally using the supplied
prefix ...
+ namespaceRegistry.register(prefix, uri);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#endPrefixMapping(java.lang.String)
+ */
+ @Override
+ public void endPrefixMapping( String prefix ) {
+ assert prefix != null;
+ // Get the current URI for this prefix ...
+ String uri = namespaceRegistry.getNamespaceForPrefix(prefix);
+ assert uri != null;
+
+ // Get the previous prefix from the stack ...
+ LinkedList<String> prefixStack = this.prefixStackByUri.get(uri);
+ assert prefixStack != null;
+ assert !prefixStack.isEmpty();
+ String existingPrefix = prefixStack.removeFirst();
+ assert prefix.equals(existingPrefix);
+
+ // If there are no previous prefixes, then remove the mapping ...
+ if (prefixStack.isEmpty()) {
+ namespaceRegistry.unregister(uri);
+ prefixStackByUri.remove(uri);
+ } else {
+ String previous = prefixStack.getFirst();
+ namespaceRegistry.register(previous, uri);
+ }
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#startEntity(java.lang.String)
+ */
+ @Override
+ public void startEntity( String name ) {
+ // Record that we've started an entity by capturing the name of the entity
...
+ currentEntityName = name;
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#endEntity(java.lang.String)
+ */
+ @Override
+ public void endEntity( String name ) {
+ // currentEntityName is nulled in 'characters(...)', not here.
+ // See DNA-231 for an issue related to this
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#startCDATA()
+ */
+ @Override
+ public void startCDATA() {
+ // CDATA sections can start in the middle of element content, so there may
already be some
+ // element content already processed ...
+ if (contentBuilder != null) endContent();
+
+ // Prepare builder for concatenating consecutive lines of CDATA
+ cDataContent = new StringBuilder();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#endCDATA()
+ */
+ @Override
+ public void endCDATA() {
+ // Output CDATA built in characters() method
+ startNode(DnaXmlLexicon.CDATA);
+ output.setProperty(currentPath, JcrLexicon.PRIMARY_TYPE, defaultPrimaryType);
+ output.setProperty(currentPath, DnaXmlLexicon.CDATA_CONTENT,
cDataContent.toString());
+ endNode();
+ // Null-out builder to free memory
+ cDataContent = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
+ */
+ @Override
+ public void characters( char[] ch,
+ int start,
+ int length ) {
+ String content = String.valueOf(ch, start, length);
+ if (cDataContent != null) {
+ // Processing the characters in the CDATA, so add to the builder
+ cDataContent.append(ch, start, length);
+ // Text within builder will be output at the end of CDATA
+ } else {
+ if (contentBuilder == null) {
+ // This is the first line of content, so we have to create the
StringBuilder ...
+ contentBuilder = new StringBuilder();
+ }
+ if (currentEntityName != null) {
+ // This is an entity reference, so rather than use the entity value
characters (the content passed
+ // into this method), we want to keep the entity reference ...
+
contentBuilder.append('&').append(currentEntityName).append(';');
+
+ // We're done reading the entity characters, so null it out
+ currentEntityName = null;
+ } else {
+ // Just append the content normally ...
+ contentBuilder.append(content);
+ }
+ // Text within builder will be output when another element or CDATA is
encountered
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.ext.DefaultHandler2#comment(char[], int, int)
+ */
+ @Override
+ public void comment( char[] ch,
+ int start,
+ int length ) {
+ // Output separate nodes for each comment since multiple are allowed
+ startNode(DnaXmlLexicon.COMMENT);
+ output.setProperty(currentPath, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.COMMENT);
+ output.setProperty(currentPath, DnaXmlLexicon.COMMENT_CONTENT, String.valueOf(ch,
start, length).trim());
+ endNode();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
java.lang.String, java.lang.String,
+ * org.xml.sax.Attributes)
+ */
+ @Override
+ public void startElement( String uri,
+ String localName,
+ String name,
+ Attributes attributes ) {
+ assert localName != null;
+
+ // Create the node with the name built from the element's name ...
+ Name nodeName = null;
+ if (nameAttribute != null) {
+ try {
+ String jcrNameValue =
attributes.getValue(nameAttribute.getNamespaceUri(), nameAttribute.getLocalName());
+ nodeName = nameFactory.create(jcrNameValue);
+ } catch (ValueFormatException e) {
+ }
+ }
+ if (nodeName == null) nodeName = nameFactory.create(uri, localName, decoder);
+ startNode(nodeName);
+
+ // Set the type of the node ...
+ if (defaultPrimaryType != null) {
+ output.setProperty(currentPath, JcrLexicon.PRIMARY_TYPE,
defaultPrimaryType);
+ }
+
+ // Now, set each attribute as a property ...
+ for (int i = 0, len = attributes.getLength(); i != len; ++i) {
+ String attributeLocalName = attributes.getLocalName(i);
+ String attributeUri = attributes.getURI(i);
+ Name attributeName = null;
+ if ((attributeUri == null || attributeUri.length() == 0) &&
attributes.getQName(i).indexOf(':') == -1) {
+ switch (this.attributeScoping) {
+ case INHERIT_ELEMENT_NAMESPACE:
+ attributeName = nameFactory.create(uri, attributeLocalName,
decoder);
+ break;
+ case USE_DEFAULT_NAMESPACE:
+ attributeName = nameFactory.create(attributeLocalName, decoder);
+ break;
+ }
+ } else {
+ attributeName = nameFactory.create(attributeUri, attributeLocalName,
decoder);
+ }
+ assert attributeName != null;
+ if (JcrLexicon.NAME.equals(attributeName)) {
+ // We don't want to record the "jcr:name" attribute since
it won't match the node name ...
+ continue;
+ }
+ Object value = attributes.getValue(i);
+ if (JcrLexicon.PRIMARY_TYPE.equals(attributeName)) {
+ // Convert it to a name ...
+ value = nameFactory.create(value);
+ }
+ output.setProperty(currentPath, attributeName, attributes.getValue(i));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.xml.XmlHandler#endElement(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ @Override
+ public void endElement( String uri,
+ String localName,
+ String name ) {
+ // Check if content still needs to be output
+ if (contentBuilder != null) endContent();
+
+ // End the current node ...
+ endNode();
+ }
+
+ /**
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException)
+ */
+ @Override
+ public void warning( SAXParseException warning ) {
+ problems.addWarning(warning, XmlSequencerI18n.warningSequencingXmlDocument,
warning);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
+ */
+ @Override
+ public void error( SAXParseException error ) {
+ problems.addError(error, XmlSequencerI18n.errorSequencingXmlDocument, error);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException)
+ */
+ @Override
+ public void fatalError( SAXParseException error ) {
+ problems.addError(error, XmlSequencerI18n.errorSequencingXmlDocument, error);
+ }
+
+ private class IndexedName {
+
+ Map<Name, List<IndexedName>> nameToIndexedNamesMap = new
HashMap<Name, List<IndexedName>>();
+
+ IndexedName() {
+ }
+ }
+}
Property changes on:
trunk/extensions/dna-sequencer-xml/src/main/java/org/jboss/dna/sequencer/xml/XmlSequencerHandler.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added:
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.sequencers.MockSequencerContext;
+import org.jboss.dna.graph.sequencers.MockSequencerOutput;
+import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author John Verhaeg
+ */
+public class InheritingXmlSequencerTest {
+
+ private static final String DOCUMENT = "dnaxml:document";
+
+ private XmlSequencer sequencer;
+ private InputStream stream;
+ private MockSequencerOutput output;
+ private URL xsd;
+ private SequencerContext context;
+
+ @Before
+ public void beforeEach() {
+ sequencer = new InheritingXmlSequencer();
+ context = new MockSequencerContext();
+ output = new MockSequencerOutput(context);
+ xsd =
this.getClass().getClassLoader().getResource("Descriptor.1.0.xsd");
+ assertThat(xsd, is(notNullValue()));
+ }
+
+ @After
+ public void afterEach() throws Exception {
+ if (stream != null) {
+ try {
+ stream.close();
+ } finally {
+ stream = null;
+ }
+ }
+ }
+
+ @Test
+ public void shouldSequenceXsds() throws IOException {
+ assertThat(sequencer.getAttributeScoping(),
is(XmlSequencer.AttributeScoping.INHERIT_ELEMENT_NAMESPACE));
+ verifyDocument(xsd);
+ verifyName("xs:schema", "jcr:primaryType",
"nt:unstructured");
+ verifyString("xs:schema", "xs:targetNamespace",
"http://ns.adobe.com/air/application/1.0");
+ verifyString("xs:schema", "xs:elementFormDefault",
"qualified");
+ verifyName("xs:schema/xs:element", "jcr:primaryType",
"nt:unstructured");
+ verifyString("xs:schema/xs:element", "xs:name",
"application");
+ }
+
+ private <T> T verify( String nodePath,
+ String property,
+ Class<T> expectedClass ) {
+ Object[] values = output.getPropertyValues(nodePath.length() == 0 ? ""
: nodePath, property);
+ assertThat(values, notNullValue());
+ assertThat(values.length, is(1));
+ Object value = values[0];
+ assertThat(value, instanceOf(expectedClass));
+ return expectedClass.cast(value);
+ }
+
+ private void verifyDocument( URL url ) throws IOException {
+ stream = url.openStream();
+ assertThat(stream, is(notNullValue()));
+ sequencer.sequence(stream, output, context);
+ verifyName("", "jcr:primaryType", DOCUMENT);
+ }
+
+ private void verifyName( String nodePath,
+ String property,
+ String expectedName ) {
+ Name name = verify(nodePath, property, Name.class);
+ assertThat(name,
is(context.getValueFactories().getNameFactory().create(expectedName)));
+ }
+
+ private void verifyString( String nodePath,
+ String property,
+ String expectedString ) {
+ String string = verify(nodePath, property, String.class);
+ assertThat(string, is(expectedString));
+ }
+}
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/InheritingXmlSequencerTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added:
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,580 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.sequencer.xml;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import org.jboss.dna.common.stats.Stopwatch;
+import org.jboss.dna.common.text.Jsr283Encoder;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.graph.JcrNtLexicon;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.PathFactory;
+import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.sequencers.MockSequencerContext;
+import org.jboss.dna.graph.sequencers.MockSequencerOutput;
+import org.jboss.dna.graph.sequencers.SequencerContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public class XmlSequencerHandlerTest {
+
+ private static final String NT_NAMESPACE_URI =
"http://www.jcp.org/jcr/nt/1.0";
+
+ private XmlSequencerHandler handler;
+ private SequencerContext context;
+ private MockSequencerOutput output;
+ private TextDecoder decoder;
+ private Name primaryType;
+ private Name nameAttribute;
+ private XmlSequencer.AttributeScoping scoping;
+ private LinkedList<Path> pathsInCreationOrder;
+
+ @Before
+ public void beforeEach() {
+ context = new MockSequencerContext();
+ output = new MockSequencerOutput(context, true);
+ context.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX,
JcrLexicon.Namespace.URI);
+ context.getNamespaceRegistry().register("nt", NT_NAMESPACE_URI);
+ context.getNamespaceRegistry().register(DnaXmlLexicon.Namespace.PREFIX,
DnaXmlLexicon.Namespace.URI);
+ context.getNamespaceRegistry().register(DnaDtdLexicon.Namespace.PREFIX,
DnaDtdLexicon.Namespace.URI);
+ decoder = null;
+ nameAttribute = JcrLexicon.NAME;
+ primaryType = JcrNtLexicon.UNSTRUCTURED;
+ scoping = XmlSequencer.AttributeScoping.USE_DEFAULT_NAMESPACE;
+ handler = new XmlSequencerHandler(output, context, nameAttribute, primaryType,
decoder, scoping);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotConstructInstanceWhenGivenNullContext() {
+ context = null;
+ new XmlSequencerHandler(output, context, nameAttribute, primaryType, decoder,
scoping);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotConstructInstanceWhenGivenNullOutput() {
+ output = null;
+ new XmlSequencerHandler(output, context, nameAttribute, primaryType, decoder,
scoping);
+ }
+
+ @Test
+ public void shouldUseDefaultDecoderIfNoneIsProvidedInConstructor() {
+ decoder = null;
+ handler = new XmlSequencerHandler(output, context, nameAttribute, primaryType,
decoder, scoping);
+ }
+
+ @Test
+ public void shouldUseDecoderProvidedInConstructor() {
+ decoder = new Jsr283Encoder();
+ new XmlSequencerHandler(output, context, nameAttribute, primaryType, decoder,
scoping);
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithoutNamespaces() throws IOException,
SAXException {
+ parse("docWithoutNamespaces.xml");
+ // Check the generated content; note that the attribute name doesn't match,
so the nodes don't get special names
+ assertDocumentNode();
+ assertNode("Cars");
+ assertNode("Cars/Hybrid");
+ assertNode("Cars/Hybrid/car[1]", "name=Toyota Prius",
"maker=Toyota", "model=Prius");
+ assertNode("Cars/Hybrid/car[2]", "name=Toyota Highlander",
"maker=Toyota", "model=Highlander");
+ assertNode("Cars/Hybrid/car[3]", "name=Nissan Altima",
"maker=Nissan", "model=Altima");
+ assertNode("Cars/Sports");
+ assertNode("Cars/Sports/car[1]", "name=Aston Martin DB9",
"maker=Aston Martin", "model=DB9");
+ assertNode("Cars/Sports/car[2]", "name=Infiniti G37",
"maker=Infiniti", "model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithNamespaces() throws IOException, SAXException
{
+ context.getNamespaceRegistry().register("c",
"http://default.namespace.com");
+ parse("docWithNamespaces.xml");
+ // Check the generated content.
+ // Note that the attribute name DOES match, so the nodes names come from
"jcr:name" attribute
+ // Also, the "jcr:name" attribute values use the default namespace,
which is "c" in the registry
+ assertDocumentNode();
+ assertNode("c:Cars");
+ assertNode("c:Cars/c:Hybrid");
+ assertNode("c:Cars/c:Hybrid/c:Toyota Prius",
"c:maker=Toyota", "c:model=Prius");
+ assertNode("c:Cars/c:Hybrid/c:Toyota Highlander",
"c:maker=Toyota", "c:model=Highlander");
+ assertNode("c:Cars/c:Hybrid/c:Nissan Altima",
"c:maker=Nissan", "c:model=Altima");
+ assertNode("c:Cars/c:Sports");
+ assertNode("c:Cars/c:Sports/c:Aston Martin DB9", "c:maker=Aston
Martin", "c:model=DB9");
+ assertNode("c:Cars/c:Sports/c:Infiniti G37",
"c:maker=Infiniti", "c:model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithNestedNamespaceDeclarations() throws
IOException, SAXException {
+ context.getNamespaceRegistry().register("c",
"http://default.namespace.com");
+ context.getNamespaceRegistry().register("i",
"http://attributes.com");
+ parse("docWithNestedNamespaces.xml");
+ // Check the generated content; note that the attribute name DOES match, so the
nodes names come from "jcr:name" attribute
+ assertDocumentNode();
+ assertNode("Cars");
+ assertNode("Cars/c:Hybrid");
+ assertNode("Cars/c:Hybrid/c:Toyota Prius", "c:maker=Toyota",
"c:model=Prius");
+ assertNode("Cars/c:Hybrid/c:Toyota Highlander",
"c:maker=Toyota", "c:model=Highlander");
+ assertNode("Cars/c:Hybrid/c:Nissan Altima", "c:maker=Nissan",
"c:model=Altima");
+ assertNode("Cars/Sports");
+ assertNode("Cars/Sports/Aston Martin DB9", "i:maker=Aston
Martin", "model=DB9");
+ assertNode("Cars/Sports/Infiniti G37", "i:maker=Infiniti",
"model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithNamespacePrefixesThatDoNotMatchRegistry()
throws IOException, SAXException {
+ context.getNamespaceRegistry().register("c",
"http://default.namespace.com");
+ parse("docWithNamespaces.xml");
+ // Check the generated content; note that the attribute name DOES match, so the
nodes names come from "jcr:name" attribute
+ assertDocumentNode();
+ assertNode("c:Cars");
+ assertNode("c:Cars/c:Hybrid");
+ assertNode("c:Cars/c:Hybrid/c:Toyota Prius",
"c:maker=Toyota", "c:model=Prius");
+ assertNode("c:Cars/c:Hybrid/c:Toyota Highlander",
"c:maker=Toyota", "c:model=Highlander");
+ assertNode("c:Cars/c:Hybrid/c:Nissan Altima",
"c:maker=Nissan", "c:model=Altima");
+ assertNode("c:Cars/c:Sports");
+ assertNode("c:Cars/c:Sports/c:Aston Martin DB9", "c:maker=Aston
Martin", "c:model=DB9");
+ assertNode("c:Cars/c:Sports/c:Infiniti G37",
"c:maker=Infiniti", "c:model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithNamespacesThatAreNotYetInRegistry() throws
IOException, SAXException {
+ NamespaceRegistry reg = context.getNamespaceRegistry();
+ reg.unregister(JcrLexicon.Namespace.URI);
+ reg.unregister(NT_NAMESPACE_URI);
+ // Verify the prefixes don't exist ...
+ assertThat(reg.getPrefixForNamespaceUri(JcrLexicon.Namespace.URI, false),
is(nullValue()));
+ assertThat(reg.getPrefixForNamespaceUri(NT_NAMESPACE_URI, false),
is(nullValue()));
+ assertThat(reg.getPrefixForNamespaceUri("http://default.namespace.com",
false), is(nullValue()));
+ // Parse the XML file ...
+ parse("docWithNestedNamespaces.xml");
+ // Get the prefix for the default namespace ...
+ String c = reg.getPrefixForNamespaceUri("http://default.namespace.com",
false);
+ String i = reg.getPrefixForNamespaceUri("http://attributes.com",
false);
+ String d = reg.getPrefixForNamespaceUri(reg.getDefaultNamespaceUri(), false);
+ assertThat("Namespace not properly registered in primary registry", c,
is(notNullValue()));
+ assertThat("Namespace not properly registered in primary registry", d,
is(notNullValue()));
+ assertThat("Namespace not properly registered in primary registry", i,
is(notNullValue()));
+ if (c.length() != 0) c = c + ":";
+ if (d.length() != 0) d = d + ":";
+ if (i.length() != 0) i = i + ":";
+ // Check the generated content; note that the attribute name DOES match, so the
nodes names come from "jcr:name" attribute
+ assertDocumentNode();
+ assertNode(d + "Cars");
+ assertNode(d + "Cars/" + c + "Hybrid");
+ assertNode(d + "Cars/" + c + "Hybrid/" + c + "Toyota
Prius", c + "maker=Toyota", c + "model=Prius");
+ assertNode(d + "Cars/" + c + "Hybrid/" + c + "Toyota
Highlander", c + "maker=Toyota", c + "model=Highlander");
+ assertNode(d + "Cars/" + c + "Hybrid/" + c + "Nissan
Altima", c + "maker=Nissan", c + "model=Altima");
+ assertNode(d + "Cars/" + d + "Sports");
+ assertNode(d + "Cars/" + d + "Sports/Aston Martin DB9", i +
"maker=Aston Martin", "model=DB9");
+ assertNode(d + "Cars/" + d + "Sports/Infiniti G37", i +
"maker=Infiniti", "model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentThatUsesNameAttribute() throws IOException,
SAXException {
+ context.getNamespaceRegistry().register("c",
"http://default.namespace.com");
+ parse("docWithNamespaces.xml");
+ // Check the generated content; note that the attribute name DOES match, so the
nodes names come from "jcr:name" attribute
+ assertDocumentNode();
+ assertNode("c:Cars");
+ assertNode("c:Cars/c:Hybrid");
+ assertNode("c:Cars/c:Hybrid/c:Toyota Prius",
"c:maker=Toyota", "c:model=Prius");
+ assertNode("c:Cars/c:Hybrid/c:Toyota Highlander",
"c:maker=Toyota", "c:model=Highlander");
+ assertNode("c:Cars/c:Hybrid/c:Nissan Altima",
"c:maker=Nissan", "c:model=Altima");
+ assertNode("c:Cars/c:Sports");
+ assertNode("c:Cars/c:Sports/c:Aston Martin DB9", "c:maker=Aston
Martin", "c:model=DB9");
+ assertNode("c:Cars/c:Sports/c:Infiniti G37",
"c:maker=Infiniti", "c:model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithoutDefaultNamespaceThatUsesNameAttribute()
throws IOException, SAXException {
+ parse("docWithNamespacesWithoutDefault.xml");
+ // Check the generated content; note that the attribute name DOES match, so the
nodes names come from "jcr:name" attribute
+ assertDocumentNode();
+ assertNode("Cars");
+ assertNode("Cars/Hybrid");
+ assertNode("Cars/Hybrid/Toyota Prius", "maker=Toyota",
"model=Prius");
+ assertNode("Cars/Hybrid/Toyota Highlander", "maker=Toyota",
"model=Highlander");
+ assertNode("Cars/Hybrid/Nissan Altima", "maker=Nissan",
"model=Altima");
+ assertNode("Cars/Sports");
+ assertNode("Cars/Sports/Aston Martin DB9", "maker=Aston
Martin", "model=DB9");
+ assertNode("Cars/Sports/Infiniti G37", "maker=Infiniti",
"model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithoutDefaultNamespaceThatUsesNoNameAttribute()
throws IOException, SAXException {
+ nameAttribute = null;
+ handler = new XmlSequencerHandler(output, context, nameAttribute, primaryType,
decoder, scoping);
+ parse("docWithNamespacesWithoutDefault.xml");
+ // Check the generated content; note that the attribute name DOES match, so the
nodes names come from "jcr:name" attribute
+ assertDocumentNode();
+ assertNode("Cars");
+ assertNode("Cars/Hybrid");
+ assertNode("Cars/Hybrid/car[1]", "maker=Toyota",
"model=Prius");
+ assertNode("Cars/Hybrid/car[2]", "maker=Toyota",
"model=Highlander");
+ assertNode("Cars/Hybrid/car[3]", "maker=Nissan",
"model=Altima");
+ assertNode("Cars/Sports");
+ assertNode("Cars/Sports/car[1]", "maker=Aston Martin",
"model=DB9");
+ assertNode("Cars/Sports/car[2]", "maker=Infiniti",
"model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentThatContainsNoContent() throws IOException,
SAXException {
+ parse("docWithOnlyRootElement.xml");
+ assertNode("",
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}document");
+ assertNode("Cars");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithXmlComments() throws IOException, SAXException
{
+ context.getNamespaceRegistry().register("c",
"http://default.namespace.com");
+ parse("docWithComments.xml");
+ assertDocumentNode();
+ assertNode("c:Cars");
+ assertComment("c:Cars/dnaxml:comment[1]", "This is a
comment");
+ assertNode("c:Cars/c:Hybrid");
+ assertNode("c:Cars/c:Hybrid/c:Toyota Prius",
"c:maker=Toyota", "c:model=Prius");
+ assertNode("c:Cars/c:Hybrid/c:Toyota Highlander",
"c:maker=Toyota", "c:model=Highlander");
+ assertNode("c:Cars/c:Hybrid/c:Nissan Altima",
"c:maker=Nissan", "c:model=Altima");
+ assertComment("c:Cars/dnaxml:comment[2]", "This is another
comment");
+ assertNode("c:Cars/c:Sports");
+ assertNode("c:Cars/c:Sports/c:Aston Martin DB9", "c:maker=Aston
Martin", "c:model=DB9");
+ assertNode("c:Cars/c:Sports/c:Infiniti G37",
"c:maker=Infiniti", "c:model=G37");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithDtdEntities() throws IOException, SAXException
{
+ // Note the expected element content has leading and trailing whitespace removed,
and any sequential
+ // whitespace is replaced with a single space
+ String longContent = "This is some long content that spans multiple lines
and should span multiple "
+ + "calls to 'character(...)'. Repeating to make
really long. This is some "
+ + "long content that spans multiple lines and should
span multiple "
+ + "calls to 'character(...)'. Repeating to make
really long. "
+ + "This is some long content that spans multiple lines
and should span multiple "
+ + "calls to 'character(...)'. Repeating to make
really long. This is some "
+ + "long content that spans multiple lines and should
span multiple "
+ + "calls to 'character(...)'. Repeating to make
really long.";
+
+ parse("docWithDtdEntities.xml");
+ assertDocumentNode("book", "-//OASIS//DTD DocBook XML
V4.4//EN", "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd");
+ assertComment("dnaxml:comment", "Document comment");
+ assertEntity(1, "%RH-ENTITIES", null,
"Common_Config/rh-entities.ent");
+ assertEntity(2, "versionNumber", "0.1");
+ assertEntity(3, "copyrightYear", "2008");
+ assertEntity(4, "copyrightHolder", "Red Hat Middleware,
LLC.");
+ assertNode("book");
+ assertNode("book/bookinfo");
+ assertNode("book/bookinfo/title");
+ assertNode("book/bookinfo/title/dnaxml:elementContent",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=JBoss DNA");
+ assertNode("book/bookinfo/releaseinfo");
+ assertNode("book/bookinfo/releaseinfo/dnaxml:elementContent",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=&versionNumber;");
+ assertNode("book/bookinfo/productnumber");
+ assertNode("book/bookinfo/productnumber/dnaxml:elementContent",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=some text with
&versionNumber;inside");
+ assertNode("book/bookinfo/abstract");
+ assertNode("book/bookinfo/abstract/dnaxml:elementContent",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=" + longContent);
+ assertNode("book/programlisting1");
+ assertNode("book/programlisting1/dnaxml:elementContent",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=<dependency>
</dependency>");
+ assertNode("book/programlisting2");
+ assertNode("book/programlisting2/dnaxml:cData",
"dnaxml:cDataContent=\n<dependency>\n</dependency>\n");
+ assertNode("book/programlisting3");
+ assertNode("book/programlisting3/dnaxml:elementContent[1]",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=mixture of text and");
+ assertNode("book/programlisting3/dnaxml:cData",
"dnaxml:cDataContent=\n<dependency>\n</dependency>\n");
+ assertNode("book/programlisting3/dnaxml:elementContent[2]",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=and some text");
+ assertComment("book/programlisting3/dnaxml:comment", "comment in
content");
+ assertNode("book/programlisting3/dnaxml:elementContent[3]",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=after.");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithProcessingInstructions() throws IOException,
SAXException {
+ parse("docWithProcessingInstructions.xml");
+ assertDocumentNode();
+ assertPI(1, "target", "content");
+ assertPI(2, "target2", "other stuff in the processing
instruction");
+ assertNode("Cars");
+ assertComment("Cars/dnaxml:comment", "This is a comment");
+ assertNode("Cars/Hybrid");
+ assertNode("Cars/Hybrid/Toyota Prius");
+ assertNode("Cars/Sports");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithCDATA() throws IOException, SAXException {
+ String cdata = "\n" + "\n" + " import
mx.events.ValidationResultEvent;\t\t\t\n"
+ + " private var
vResult:ValidationResultEvent;\n" + "\t\t\t\n"
+ + " // Event handler to validate and format
input.\n"
+ + " private function Format():void {\n" +
" \n"
+ + " vResult = numVal.validate();\n" +
"\n"
+ + " if
(vResult.type==ValidationResultEvent.VALID) {\n"
+ + " var
temp:Number=Number(priceUS.text); \n"
+ + " formattedUSPrice.text=
usdFormatter.format(temp);\n"
+ + " }\n" + "
\n" + " else {\n"
+ + "
formattedUSPrice.text=\"\";\n" + " }\n" +
" }\n"
+ + " ";
+ parse("docWithCDATA.xml");
+ assertDocumentNode();
+ assertComment("dnaxml:comment", "Simple example to demonstrate the
CurrencyFormatter.");
+ assertNode("mx:Application");
+ assertNode("mx:Application/mx:Script");
+ assertCdata("mx:Application/mx:Script/dnaxml:cData", cdata);
+ // Now there's an element that contains a mixture of regular element content,
CDATA content, and comments
+ assertNode("mx:Application/programlisting3");
+ assertNode("mx:Application/programlisting3/dnaxml:elementContent[1]",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=mixture of text and");
+ assertNode("mx:Application/programlisting3/dnaxml:cData",
+ "dnaxml:cDataContent=\n<dependency>entities like >
are not replaced in a CDATA\n</dependency>\n");
+ assertNode("mx:Application/programlisting3/dnaxml:elementContent[2]",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=and some text");
+ assertComment("mx:Application/programlisting3/dnaxml:comment",
"comment in content");
+ assertNode("mx:Application/programlisting3/dnaxml:elementContent[3]",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}elementContent",
+ "dnaxml:elementContent=after.");
+ // Now the final element
+ assertNode("mx:Application/mx:NumberValidator",
+ "id=numVal",
+ "source={priceUS}",
+ "property=text",
+ "allowNegative=true",
+ "domain=real");
+ assertNoMoreNodes();
+ }
+
+ @Test
+ public void shouldParseXmlDocumentWithDtd() throws IOException, SAXException {
+ parse("master.xml");
+ assertDocumentNode("book", "-//OASIS//DTD DocBook XML
V4.4//EN", "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd");
+ }
+
+ protected void assertNoMoreNodes() {
+ if (!pathsInCreationOrder.isEmpty()) {
+ fail("Extra nodes were not expected:" + pathsInCreationOrder);
+ }
+ }
+
+ protected void assertNode( String path,
+ String... properties ) {
+ // Append an index to the path if not there ...
+ if (path.length() != 0 && !path.endsWith("]")) {
+ path = path + "[1]";
+ }
+
+ // Create the expected path ...
+ PathFactory factory = context.getValueFactories().getPathFactory();
+ Path expectedPath = null;
+ if (path.length() == 0) {
+ expectedPath = factory.createRelativePath();
+ } else {
+ expectedPath = factory.create(path);
+ }
+
+ // Pop the next node and compare ...
+ Path next = this.pathsInCreationOrder.removeFirst();
+ assertThat(next, is(expectedPath));
+
+ // Create the list of properties ...
+ Map<Name, Property> expectedProperties = new HashMap<Name,
Property>();
+ for (String propertyString : properties) {
+ String[] strings = propertyString.split("=");
+ if (strings.length < 2) continue;
+ Name name = context.getValueFactories().getNameFactory().create(strings[0]);
+ Object[] values = new Object[strings.length - 1];
+ for (int i = 1; i != strings.length; ++i) {
+ values[i - 1] = strings[i];
+ }
+ Property property = context.getPropertyFactory().create(name, values);
+ expectedProperties.put(name, property);
+ }
+ // If properties does not contain a primaryType property, then add the default
...
+ if (!expectedProperties.containsKey(JcrLexicon.PRIMARY_TYPE)) {
+ Property property =
context.getPropertyFactory().create(JcrLexicon.PRIMARY_TYPE, primaryType);
+ expectedProperties.put(property.getName(), property);
+ }
+
+ // Now get the Properties for this path ...
+ Map<Name, Property> actualProperties = output.getProperties(expectedPath);
+ assertThat("node not found", actualProperties, is(notNullValue()));
+ for (Property actual : actualProperties.values()) {
+ Property expected = expectedProperties.remove(actual.getName());
+ assertThat("unexpected actual property: " + actual, expected,
is(notNullValue()));
+ assertThat(actual, is(expected));
+ }
+ if (!expectedProperties.isEmpty()) {
+ StringBuilder msg = new StringBuilder("missing actual properties:
");
+ boolean isFirst = true;
+ for (Property expected : expectedProperties.values()) {
+ if (!isFirst) msg.append(", ");
+ else isFirst = false;
+ msg.append(expected.getName());
+ }
+ assertThat(msg.toString(), expectedProperties.isEmpty(), is(true));
+ }
+ }
+
+ protected void assertComment( String path,
+ String comment ) {
+ assertNode(path,
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}comment",
"dnaxml:commentContent=" + comment.trim());
+ }
+
+ protected void assertCdata( String path,
+ String content ) {
+ // Append an index to the path if not there ...
+ if (path.length() != 0 && !path.endsWith("]")) {
+ path = path + "[1]";
+ }
+ PathFactory factory = context.getValueFactories().getPathFactory();
+ Path expectedPath = factory.create("/" + path);
+
+ // Pop the next node and compare ...
+ Path next = this.pathsInCreationOrder.removeFirst();
+ assertThat(next, is(expectedPath));
+
+ // There should be a single property ...
+ Property actualPrimaryType = output.getProperty(expectedPath,
JcrLexicon.PRIMARY_TYPE);
+ assertThat(actualPrimaryType.getValues().next(),
is((Object)JcrNtLexicon.UNSTRUCTURED));
+ Property actual = output.getProperty(expectedPath, DnaXmlLexicon.CDATA_CONTENT);
+ assertThat("expected one CDATA property", actual, is(notNullValue()));
+ Property expected =
context.getPropertyFactory().create(DnaXmlLexicon.CDATA_CONTENT, content);
+ assertThat("CDATA content differed", actual, is(expected));
+ }
+
+ protected void assertDocumentNode() {
+ assertNode("",
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}document");
+ }
+
+ protected void assertDocumentNode( String name,
+ String publicId,
+ String systemId ) {
+ assertNode("",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}document",
+ "dnadtd:name=" + name,
+ "dnadtd:publicId=" + publicId,
+ "dnadtd:systemId=" + systemId);
+ }
+
+ protected void assertEntity( int index,
+ String entityName,
+ String value ) {
+ String path = "dnadtd:entity[" + index + "]";
+ assertNode(path,
"jcr:primaryType={http://www.jboss.org/dna/dtd/1.0}entity",
"dnadtd:name=" + entityName, "dnadtd:value="
+
+ value);
+ }
+
+ protected void assertEntity( int index,
+ String entityName,
+ String publicId,
+ String systemId ) {
+ String path = "dnadtd:entity[" + index + "]";
+ if (publicId != null) {
+ assertNode(path,
+
"jcr:primaryType={http://www.jboss.org/dna/dtd/1.0}entity",
+ "dnadtd:name=" + entityName,
+ "dnadtd:publicId=" + publicId,
+ "dnadtd:systemId=" + systemId);
+ } else {
+ assertNode(path,
+
"jcr:primaryType={http://www.jboss.org/dna/dtd/1.0}entity",
+ "dnadtd:name=" + entityName,
+ "dnadtd:systemId=" + systemId);
+ }
+ }
+
+ protected void assertPI( int index,
+ String target,
+ String data ) {
+ assertNode("dnaxml:processingInstruction[" + index + "]",
+
"jcr:primaryType={http://www.jboss.org/dna/xml/1.0}processingInstruction",
+ "dnaxml:target=" + target,
+ "dnaxml:processingInstructionContent=" + data);
+ }
+
+ protected void parse( String relativePathToXmlFile ) throws IOException, SAXException
{
+ Stopwatch sw = new Stopwatch();
+ sw.start();
+ InputStream stream =
getClass().getClassLoader().getResourceAsStream(relativePathToXmlFile);
+ try {
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ reader.setContentHandler(handler);
+ reader.setErrorHandler(handler);
+ // Ensure handler acting as entity resolver 2
+ reader.setProperty(XmlSequencer.DECL_HANDLER_FEATURE, handler);
+ // Ensure handler acting as lexical handler
+ reader.setProperty(XmlSequencer.LEXICAL_HANDLER_FEATURE, handler);
+ // Ensure handler acting as entity resolver 2
+ XmlSequencer.setFeature(reader, XmlSequencer.ENTITY_RESOLVER_2_FEATURE,
true);
+ // Prevent loading of external DTDs
+ XmlSequencer.setFeature(reader, XmlSequencer.LOAD_EXTERNAL_DTDS_FEATURE,
false);
+ // Prevent the resolving of DTD entities into fully-qualified URIS
+ XmlSequencer.setFeature(reader, XmlSequencer.RESOLVE_DTD_URIS_FEATURE,
false);
+ reader.parse(new InputSource(stream));
+ } finally {
+ if (stream != null) stream.close();
+ sw.stop();
+ System.out.println("Parsing: " + sw);
+ }
+ pathsInCreationOrder = new LinkedList<Path>(output.getOrderOfCreation());
+ }
+}
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerHandlerTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java 2008-11-10
23:57:53 UTC (rev 618)
+++
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java 2008-11-12
04:31:14 UTC (rev 619)
@@ -99,13 +99,14 @@
verifyDocument(xml1);
verifyName(COMMENT + "[1]", "jcr:primaryType", COMMENT);
String text = verify(COMMENT + "[1]", COMMENT_CONTENT, String.class);
- assertThat(text.startsWith("\n Licensed to the Apache Software Foundation
(ASF)"), is(true));
- assertThat(text.endsWith(" limitations under the License.\n"),
is(true));
+ assertThat(text.startsWith("Licensed to the Apache Software Foundation
(ASF)"), is(true));
+ assertThat(text.indexOf('\n') > 0, is(true));
+ assertThat(text.endsWith(" limitations under the License."),
is(true));
verifyString("/", DTD_NAME, "Repository");
verifyString("/", DTD_PUBLIC_ID, "-//The Apache Software
Foundation//DTD Jackrabbit 1.2//EN");
verifyString("/", DTD_SYSTEM_ID,
"http://jackrabbit.apache.org/dtd/repository-1.2.dtd");
verifyName(COMMENT + "[2]", "jcr:primaryType", COMMENT);
- verifyString(COMMENT + "[2]", COMMENT_CONTENT, " Example
Repository Configuration File ");
+ verifyString(COMMENT + "[2]", COMMENT_CONTENT, "Example Repository
Configuration File");
verifyName("Repository[1]", "jcr:primaryType",
"nt:unstructured");
verifyName("Repository[1]/" + COMMENT + "[1]",
"jcr:primaryType", COMMENT);
}
@@ -114,9 +115,9 @@
public void shouldHandleNamespaces() throws IOException {
verifyDocument(xml2);
verifyName("book[1]/bookinfo[1]/xi:include[1]",
"jcr:primaryType", "nt:unstructured");
- verifyString("book[1]/bookinfo[1]/xi:include[1]", "xi:href",
"Author_Group.xml");
+ verifyString("book[1]/bookinfo[1]/xi:include[1]", "href",
"Author_Group.xml");
verifyName("book[1]/bookinfo[1]/xi:include[2]",
"jcr:primaryType", "nt:unstructured");
- verifyString("book[1]/bookinfo[1]/xi:include[2]", "xi:href",
"Legal_Notice.xml");
+ verifyString("book[1]/bookinfo[1]/xi:include[2]", "href",
"Legal_Notice.xml");
}
@Test
@@ -175,18 +176,19 @@
@Test
public void shouldSequenceXsds() throws IOException {
+
sequencer.setAttributeScoping(XmlSequencer.AttributeScoping.INHERIT_ELEMENT_NAMESPACE);
verifyDocument(xsd);
- verifyName("xs:schema[1]", "jcr:primaryType",
"nt:unstructured");
- verifyString("xs:schema[1]", "xs:targetNamespace",
"http://ns.adobe.com/air/application/1.0");
- verifyString("xs:schema[1]", "xs:elementFormDefault",
"qualified");
- verifyName("xs:schema[1]/xs:element[1]", "jcr:primaryType",
"nt:unstructured");
- verifyString("xs:schema[1]/xs:element[1]", "xs:name",
"application");
+ verifyName("xs:schema", "jcr:primaryType",
"nt:unstructured");
+ verifyString("xs:schema", "xs:targetNamespace",
"http://ns.adobe.com/air/application/1.0");
+ verifyString("xs:schema", "xs:elementFormDefault",
"qualified");
+ verifyName("xs:schema/xs:element", "jcr:primaryType",
"nt:unstructured");
+ verifyString("xs:schema/xs:element", "xs:name",
"application");
}
private <T> T verify( String nodePath,
String property,
Class<T> expectedClass ) {
- Object[] values = output.getPropertyValues(nodePath.length() == 0 ? "."
: nodePath, property);
+ Object[] values = output.getPropertyValues(nodePath.length() == 0 ? ""
: nodePath, property);
assertThat(values, notNullValue());
assertThat(values.length, is(1));
Object value = values[0];
Added: trunk/extensions/dna-sequencer-xml/src/test/resources/docWithCDATA.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/docWithCDATA.xml
(rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/docWithCDATA.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Simple example to demonstrate the CurrencyFormatter. -->
+<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml">
+
+ <mx:Script>
+ <![CDATA[
+
+ import mx.events.ValidationResultEvent;
+ private var vResult:ValidationResultEvent;
+
+ // Event handler to validate and format input.
+ private function Format():void {
+
+ vResult = numVal.validate();
+
+ if (vResult.type==ValidationResultEvent.VALID) {
+ var temp:Number=Number(priceUS.text);
+ formattedUSPrice.text= usdFormatter.format(temp);
+ }
+
+ else {
+ formattedUSPrice.text="";
+ }
+ }
+ ]]>
+ </mx:Script>
+ <programlisting3>mixture of text and <![CDATA[
+<dependency>entities like > are not replaced in a CDATA
+</dependency>
+]]> and some text <!-- comment in content -->after.</programlisting3>
+
+ <mx:NumberValidator id="numVal" source="{priceUS}"
property="text"
+ allowNegative="true" domain="real"/>
+</mx:Application>
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithCDATA.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/extensions/dna-sequencer-xml/src/test/resources/docWithComments.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/docWithComments.xml
(rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/docWithComments.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Cars xmlns="http://default.namespace.com"
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+ <!-- This is a comment -->
+ <Hybrid>
+ <car jcr:name="Toyota Prius" maker="Toyota"
model="Prius"/>
+ <car jcr:name="Toyota Highlander" maker="Toyota"
model="Highlander"/>
+ <car jcr:name="Nissan Altima" maker="Nissan"
model="Altima"/>
+ </Hybrid>
+ <!--
+ This is another comment
+ -->
+ <Sports>
+ <car jcr:name="Aston Martin DB9" maker="Aston Martin"
model="DB9"/>
+ <car jcr:name="Infiniti G37" maker="Infiniti"
model="G37" />
+ </Sports>
+</Cars>
\ No newline at end of file
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithComments.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/extensions/dna-sequencer-xml/src/test/resources/docWithDtdEntities.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/docWithDtdEntities.xml
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithDtdEntities.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Document comment -->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!ENTITY % RH-ENTITIES SYSTEM "Common_Config/rh-entities.ent">
+<!ENTITY versionNumber "0.1">
+<!ENTITY copyrightYear "2008">
+<!ENTITY copyrightHolder "Red Hat Middleware, LLC.">]>
+<book>
+ <bookinfo>
+ <title>JBoss DNA</title>
+ <releaseinfo>&versionNumber;</releaseinfo>
+ <productnumber>some text with &versionNumber;inside
+ </productnumber>
+ <abstract>
+ This is some long content that spans multiple lines and should span multiple calls
to 'character(...)'. Repeating to make really long. This is some
+long content that spans multiple lines and should span multiple
+calls to 'character(...)'. Repeating to make really long. This is some long
content that spans multiple lines and should span multiple calls to
'character(...)'. Repeating to make really long. This is some long content that
spans multiple lines and should span multiple calls to 'character(...)'.
Repeating to make really long.
+ </abstract>
+ </bookinfo>
+ <programlisting1>
+<dependency>
+</dependency>
+ </programlisting1>
+ <programlisting2><![CDATA[
+<dependency>
+</dependency>
+]]></programlisting2>
+ <programlisting3>mixture of text and <![CDATA[
+<dependency>
+</dependency>
+]]> and some text <!-- comment in content -->after.</programlisting3>
+</book>
\ No newline at end of file
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithDtdEntities.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespaces.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespaces.xml
(rev 0)
+++ trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespaces.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Cars xmlns="http://default.namespace.com"
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+ <Hybrid>
+ <car jcr:name="Toyota Prius" maker="Toyota"
model="Prius"/>
+ <car jcr:name="Toyota Highlander" maker="Toyota"
model="Highlander"/>
+ <car jcr:name="Nissan Altima" maker="Nissan"
model="Altima"/>
+ </Hybrid>
+ <Sports>
+ <car jcr:name="Aston Martin DB9" maker="Aston Martin"
model="DB9"/>
+ <car jcr:name="Infiniti G37" maker="Infiniti"
model="G37" />
+ </Sports>
+</Cars>
\ No newline at end of file
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespaces.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespacesWithoutDefault.xml
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespacesWithoutDefault.xml
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespacesWithoutDefault.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Cars
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+ <Hybrid>
+ <car jcr:name="Toyota Prius" maker="Toyota"
model="Prius"/>
+ <car jcr:name="Toyota Highlander" maker="Toyota"
model="Highlander"/>
+ <car jcr:name="Nissan Altima" maker="Nissan"
model="Altima"/>
+ </Hybrid>
+ <Sports>
+ <car jcr:name="Aston Martin DB9" maker="Aston Martin"
model="DB9"/>
+ <car jcr:name="Infiniti G37" maker="Infiniti"
model="G37" />
+ </Sports>
+</Cars>
\ No newline at end of file
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNamespacesWithoutDefault.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNestedNamespaces.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNestedNamespaces.xml
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNestedNamespaces.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Cars
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+ <Hybrid xmlns="http://default.namespace.com">
+ <car jcr:name="Toyota Prius" maker="Toyota"
model="Prius"/>
+ <car jcr:name="Toyota Highlander" maker="Toyota"
model="Highlander"/>
+ <car jcr:name="Nissan Altima" maker="Nissan"
model="Altima"/>
+ </Hybrid>
+ <Sports
xmlns:jcr2="http://www.jcp.org/jcr/1.0"
xmlns:info="http://attributes.com">
+ <car jcr2:name="Aston Martin DB9" info:maker="Aston
Martin" model="DB9"/>
+ <car jcr:name="Infiniti G37" info:maker="Infiniti"
model="G37" />
+ </Sports>
+</Cars>
\ No newline at end of file
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithNestedNamespaces.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/extensions/dna-sequencer-xml/src/test/resources/docWithOnlyRootElement.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/docWithOnlyRootElement.xml
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithOnlyRootElement.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Cars>
+</Cars>
\ No newline at end of file
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithOnlyRootElement.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithProcessingInstructions.xml
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithProcessingInstructions.xml
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithProcessingInstructions.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?target content ?>
+<?target2 other stuff in the processing instruction ?>
+<Cars
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+ <!-- This is a comment -->
+ <Hybrid>
+ <car jcr:name="Toyota Prius"/>
+ </Hybrid>
+ <Sports>
+ </Sports>
+</Cars>
\ No newline at end of file
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithProcessingInstructions.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/extensions/dna-sequencer-xml/src/test/resources/docWithoutNamespaces.xml
===================================================================
--- trunk/extensions/dna-sequencer-xml/src/test/resources/docWithoutNamespaces.xml
(rev 0)
+++
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithoutNamespaces.xml 2008-11-12
04:31:14 UTC (rev 619)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Cars>
+ <Hybrid>
+ <car name="Toyota Prius" maker="Toyota"
model="Prius"/>
+ <car name="Toyota Highlander" maker="Toyota"
model="Highlander"/>
+ <car name="Nissan Altima" maker="Nissan"
model="Altima"/>
+ </Hybrid>
+ <Sports>
+ <car name="Aston Martin DB9" maker="Aston Martin"
model="DB9"/>
+ <car name="Infiniti G37" maker="Infiniti"
model="G37" />
+ </Sports>
+</Cars>
\ No newline at end of file
Property changes on:
trunk/extensions/dna-sequencer-xml/src/test/resources/docWithoutNamespaces.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain