package client.net.sf.saxon.ce.event;
import client.net.sf.saxon.ce.om.AttributeCollection;
import client.net.sf.saxon.ce.om.NamespaceBinding;
import client.net.sf.saxon.ce.trans.XPathException;
import java.util.ArrayList;
import java.util.List;
/**
* StartTagBuffer is a ProxyReceiver that buffers attributes and namespace events within a start tag.
* It maintains details of the namespace context, and a full set of attribute information, on behalf
* of other filters that need access to namespace information or need to process attributes in arbitrary
* order.
*/
public class StartTagBuffer extends ProxyReceiver {
// Details of the pending element event
protected int elementNameCode;
protected int elementProperties;
// Details of pending attribute events
protected AttributeCollection bufferedAttributes;
protected List<NamespaceBinding> bufferedNamespaces = new ArrayList();
int attCount = 0;
/**
* Set the pipeline configuration
* @param pipe the pipeline configuration
*/
public void setPipelineConfiguration(PipelineConfiguration pipe) {
super.setPipelineConfiguration(pipe);
bufferedAttributes = new AttributeCollection(pipe.getConfiguration());
}
/**
* startElement
*/
public void startElement(int nameCode, int properties) throws XPathException {
elementNameCode = nameCode;
elementProperties = properties;
bufferedAttributes.clear();
bufferedNamespaces.clear();
attCount = 0;
}
@Override
public void namespace(NamespaceBinding nsBinding, int properties) throws XPathException {
bufferedNamespaces.add(nsBinding);
}
/**
* Notify an attribute. Attributes are notified after the startElement event, and before any
* children. Namespaces and attributes may be intermingled.
*
* @param nameCode The name of the attribute, as held in the name pool
* @throws IllegalStateException: attempt to output an attribute when there is no open element
* start tag
*/
public void attribute(int nameCode, CharSequence value)
throws XPathException {
bufferedAttributes.addAttribute(nameCode, value.toString());
// Note: we're relying on the fact that AttributeCollection can hold two attributes of the same name
// and maintain their order, because the check for duplicate attributes is not done until later in the
// pipeline. We validate both the attributes (see Bugzilla #4600 which legitimizes this.)
}
/**
* startContent: Add any namespace undeclarations needed to stop
* namespaces being inherited from parent elements
*/
public void startContent() throws XPathException {
nextReceiver.startElement(elementNameCode, elementProperties);
final int length = bufferedAttributes.getLength();
for (int i=0; i<length; i++) {
nextReceiver.attribute(bufferedAttributes.getNameCode(i),
bufferedAttributes.getValue(i)
);
}
for (NamespaceBinding nb : bufferedNamespaces) {
nextReceiver.namespace(nb, 0);
}
nextReceiver.startContent();
}
/**
* Get the value of the current attribute with a given nameCode
* @param nameCode the name of the required attribute
* @return the attribute value, or null if the attribute is not present
*/
public String getAttribute(int nameCode) {
return bufferedAttributes.getValueByFingerprint(nameCode & 0xfffff);
}
}
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.