All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.instruct.FixedElement Maven / Gradle / Ivy

Go to download

Provides a basic XSLT 2.0 and XQuery 1.0 processor (W3C Recommendations, January 2007). Command line interfaces and implementations of several Java APIs (DOM, XPath, s9api) are also included.

The newest version!
package net.sf.saxon.instruct;
import net.sf.saxon.Configuration;
import net.sf.saxon.event.Receiver;
import net.sf.saxon.expr.*;
import net.sf.saxon.om.NamePool;
import net.sf.saxon.om.QNameException;
import net.sf.saxon.om.StandardNames;
import net.sf.saxon.om.Validation;
import net.sf.saxon.pattern.CombinedNodeTest;
import net.sf.saxon.pattern.ContentTypeTest;
import net.sf.saxon.pattern.NameTest;
import net.sf.saxon.pattern.NodeKindTest;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trace.InstructionInfo;
import net.sf.saxon.trace.Location;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.*;

import java.util.Iterator;


/**
* An instruction that creates an element node whose name is known statically.
 * Used for literal results elements in XSLT, for direct element constructors
 * in XQuery, and for xsl:element in cases where the name and namespace are
 * known statically.
*/

public class FixedElement extends ElementCreator {

    // TODO: create a separate class for the case where schema validation is involved

    // TODO: if the sequence of child elements is statically known (e.g. if the content is a Block consisting
    // entirely of FixedElement instructions) then validate against the schema content model at compile time.

    private int nameCode;
    protected int[] namespaceCodes = null;
    private ItemType itemType;

    /**
     * Create an instruction that creates a new element node
     * @param nameCode Represents the name of the element node
     * @param namespaceCodes List of namespaces to be added to the element node.
     *                       May be null if none are required.
     * @param inheritNamespaces true if the children of this element are to inherit its namespaces
     * @param schemaType Type annotation for the new element node
     * @param validation Validation mode to be applied, for example STRICT, LAX, SKIP
     */
    public FixedElement(int nameCode,
                        int[] namespaceCodes,
                        boolean inheritNamespaces,
                        SchemaType schemaType,
                        int validation) {
        this.nameCode = nameCode;
        this.namespaceCodes = namespaceCodes;
        this.inheritNamespaces = inheritNamespaces;
        setSchemaType(schemaType);
        this.validation = validation;
        preservingTypes = schemaType == null && validation == Validation.PRESERVE;
    }

    public InstructionInfo getInstructionInfo() {
        InstructionDetails details = (InstructionDetails)super.getInstructionInfo();
        details.setConstructType(Location.LITERAL_RESULT_ELEMENT);
        details.setObjectNameCode(nameCode);
        return details;
    }

    /**
     * Simplify an expression. This performs any context-independent rewriting
     * @param visitor the expression visitor
     * @return the simplified expression
     * @throws net.sf.saxon.trans.XPathException
     *          if an error is discovered during expression rewriting
     */

    public Expression simplify(ExpressionVisitor visitor) throws XPathException {
        final Configuration config = visitor.getConfiguration();
        setLazyConstruction(config.isLazyConstructionMode());
        preservingTypes |= !config.isSchemaAware(Configuration.XML_SCHEMA);
        int val = validation;
        SchemaType type = getSchemaType();
        itemType = computeFixedElementItemType(this, visitor.getStaticContext(),
                val, type, nameCode, content);
        return super.simplify(visitor);
    }


    public Expression optimize(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException {
        Expression e = super.optimize(visitor, contextItemType);
        if (e != this) {
            return e;
        }
        // Remove any unnecessary creation of namespace nodes by child literal result elements.
        // Specifically, if this instruction creates a namespace node, then a child literal result element
        // doesn't need to create the same namespace if all the following conditions are true:
        // (a) the child element is in the same namespace as its parent, and
        // (b) this element doesn't specify xsl:inherit-namespaces="no"
        // (c) the child element is incapable of creating attributes in a non-null namespace

        if (!inheritNamespaces) {
            return this;
        }
        if (namespaceCodes == null || namespaceCodes.length == 0) {
            return this;
        }
        NamePool pool = visitor.getExecutable().getConfiguration().getNamePool();
        int uriCode = getURICode(pool);
        if (content instanceof FixedElement) {
            if (((FixedElement)content).getURICode(pool) == uriCode) {
                ((FixedElement)content).removeRedundantNamespaces(visitor, namespaceCodes);
            }
            return this;
        }
        if (content instanceof Block) {
            Iterator iter = content.iterateSubExpressions();
            while (iter.hasNext()) {
                Expression exp = (Expression)iter.next();
                if (exp instanceof FixedElement && ((FixedElement)exp).getURICode(pool) == uriCode) {
                    ((FixedElement)exp).removeRedundantNamespaces(visitor, namespaceCodes);
                }
            }
        }
        return this;
    }

    /**
     * Remove namespaces that are not required for this element because they are output on
     * the parent element
     * @param visitor the expression visitor
     * @param parentNamespaces the namespaces that are output by the parent element
     */

    private void removeRedundantNamespaces(ExpressionVisitor visitor, int[] parentNamespaces) {
        // It's only safe to remove any namespaces if the element is incapable of creating any attribute nodes
        // in a non-null namespace
        // This is because namespaces created on this element take precedence over namespaces created by namespace
        // fixup based on the prefix used in the attribute name (see atrs24)
        if (namespaceCodes == null || namespaceCodes.length == 0) {
            return;
        }
        TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
        ItemType contentType = content.getItemType(th);
        boolean ok = th.relationship(contentType, NodeKindTest.ATTRIBUTE) == TypeHierarchy.DISJOINT;
        if (!ok) {
            // if the content might include attributes, discount any that are known to be in the null namespace
            if (content instanceof Block) {
                ok = true;
                Iterator iter = content.iterateSubExpressions();
                while (iter.hasNext()) {
                    Expression exp = (Expression)iter.next();
                    if (exp instanceof FixedAttribute) {
                        int attNameCode = ((FixedAttribute)exp).getAttributeNameCode();
                        if (NamePool.getPrefixIndex(attNameCode) != 0) {
                            ok = false;
                            break;
                        }
                    } else {
                        ItemType childType = exp.getItemType(th);
                        if (th.relationship(childType, NodeKindTest.ATTRIBUTE) != TypeHierarchy.DISJOINT) {
                            ok = false;
                            break;
                        }
                    }
                }
            }
        }
        if (ok) {
            int removed = 0;
            for (int i=0; i 0) {
                if (removed == namespaceCodes.length) {
                    namespaceCodes = null;
                } else {
                    int[] ns2 = new int[namespaceCodes.length - removed];
                    int j=0;
                    for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy