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

net.sf.saxon.style.XSLPackage Maven / Gradle / Ivy

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2015 Saxonica Limited.
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.style;

import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.lib.Validation;
import net.sf.saxon.om.*;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.iter.AxisIterator;
import net.sf.saxon.tree.linked.NodeImpl;
import net.sf.saxon.tree.util.AttributeCollectionImpl;
import net.sf.saxon.type.SchemaType;
import net.sf.saxon.type.Type;
import net.sf.saxon.value.Whitespace;

/**
 * Handler for xsl:package elements. Explicit xsl:package elements are not permitted in Saxon-HE, but
 * implicit packages are created, so the class is present in HE. The top-level module of a stylesheet/package
 * will always be represented by an XSLPackage object, but if the original name was xsl:stylesheet or xsl:transform
 * then this original name will be present as the name of the element.
 */
public class XSLPackage extends XSLModuleRoot {

    private String nameAtt = null;
    private PackageVersion packageVersion = null;
    private boolean declaredModes = true;

    /**
     * Initialise a new ElementImpl with an element name
     *
     * @param elemName       Integer representing the element name, with namespaces resolved
     * @param elementType    the schema type of the element node
     * @param atts           The attribute list: always null
     * @param parent         The parent node
     * @param sequenceNumber Integer identifying this element within the document
     */
    @Override
    public void initialise(NodeName elemName, SchemaType elementType, AttributeCollectionImpl atts, NodeInfo parent, int sequenceNumber) {
        super.initialise(elemName, elementType, atts, parent, sequenceNumber);
        declaredModes = getLocalPart().equals("package");
    }

    /**
     * Get the name of the package (the value of its @name attribute)
     * @return the name of the package, or null if the @name attribute is omitted
     */

    public String getName() {
        if (nameAtt == null) {
            try {
                prepareAttributes();
            } catch (XPathException e) {
                nameAtt = "default";
            }
        }
        return nameAtt;
    }

    /**
     * Get the requested XSLT version (the value of the @version attribute)
     * @return the value of the @version attribute, times ten as an integer
     */

    public int getVersion() {
        if (version == -1) {
            try {
                prepareAttributes();
            } catch (XPathException e) {
                version = 30;
            }
        }
        return version;
    }

    /**
     * Get the package version (the value of the @package-version attribute)
     * @return the value of the @package-version attribute, defaulting to "1.0"
     */
    public PackageVersion getPackageVersion() {
        if (packageVersion == null) {
            try {
                prepareAttributes();
            } catch (XPathException e) {
                packageVersion = PackageVersion.ONE;
            }
        }
        return packageVersion;
    }



    @Override
    protected void prepareAttributes() throws XPathException {
        if (nameAtt != null) {
            // already done
            return;
        }

        String inputTypeAnnotationsAtt = null;
        AttributeCollection atts = getAttributeList();

        for (int a = 0; a < atts.getLength(); a++) {
            String f = atts.getQName(a);
            if (f.equals("name") && getLocalPart().equals("package")) {
                nameAtt = Whitespace.trim(atts.getValue(a));
            } else if (f.equals("id")) {
                // no action
            } else if (f.equals("version")) {
                if (version == -1) {
                    processVersionAttribute("");
                }
            } else if (f.equals("package-version") && getLocalPart().equals("package")) {
                String pversion = Whitespace.trim(atts.getValue(a));
                try {
                    packageVersion = new PackageVersion(pversion);
                    //packageVersion = NestedIntegerValue.parse(pversion);
                } catch (XPathException ex) {
                    throw new XPathException("Error in xsl:package - The package-version attribute has incorrect character(s): " + pversion);
                }
            } else if (f.equals("declared-modes") && getLocalPart().equals("package")) {
                declaredModes = processBooleanAttribute("declared-modes", atts.getValue(a));
            } else if (f.equals("default-validation")) {
                String val = Whitespace.trim(atts.getValue(a));
                defaultValidation = Validation.getCode(val);
                if (defaultValidation == Validation.INVALID ||
                    defaultValidation == Validation.STRICT || defaultValidation == Validation.LAX) {
                    compileError("Invalid value for default-validation attribute. " +
                        "Permitted values are (preserve, strip)", "XTSE0020");
                } else if (!isSchemaAware() && defaultValidation != Validation.STRIP) {
                    defaultValidation = Validation.STRIP;
                    compileError("default-validation='" + val + "' requires a schema-aware processor",
                            "XTSE1660");
                }
            } else if (f.equals("input-type-annotations")) {
                inputTypeAnnotationsAtt = atts.getValue(a);
            } else {
                checkUnknownAttribute(atts.getNodeName(a));
            }
        }

        if (packageVersion == null) {
            packageVersion = PackageVersion.ONE;
        }

        if (version == -1) {
            version = 30;
            reportAbsence("version");
        }
        if (inputTypeAnnotationsAtt != null) {
            if (inputTypeAnnotationsAtt.equals("strip")) {
                //setInputTypeAnnotations(ANNOTATION_STRIP);
            } else if (inputTypeAnnotationsAtt.equals("preserve")) {
                //setInputTypeAnnotations(ANNOTATION_PRESERVE);
            } else if (inputTypeAnnotationsAtt.equals("unspecified")) {
                //
            } else {
                compileError("Invalid value for input-type-annotations attribute. " +
                        "Permitted values are (strip, preserve, unspecified)", "XTSE0020");
            }
        }

    }

    /**
     * Determine whether forwards-compatible mode is enabled for this element
     *
     * @return true if forwards-compatible mode is enabled
     */

    public boolean forwardsCompatibleModeIsEnabled() {
        return false;
    }

    /**
     * Ask whether it is required that modes be explicitly declared
     *
     * @return true if modes referenced within this package must be explicitly declared
     */
    @Override
    public boolean isDeclaredModes() {
        if (nameAtt == null) {
            try {
                prepareAttributes();
            } catch (XPathException e) {
                // it will be reported later
                nameAtt = null;
            }
        }
        return declaredModes;
    }

    /**
     * Recursive walk through the stylesheet to validate all nodes
     * @param decl not used
     * @throws XPathException if invalid
     */


    public void validate(ComponentDeclaration decl) throws XPathException {

        AxisIterator kids = iterateAxis(AxisInfo.CHILD);
        NodeImpl child;
        while ((child = (NodeImpl)kids.next()) != null) {
            int fp = child.getFingerprint();
            if (child.getNodeKind() == Type.TEXT ||
                    (child instanceof StyleElement && ((StyleElement) child).isDeclaration()) ||
                    child instanceof DataElement ) {
                // all is well
            } else if (getLocalPart().equals("package") &&
                    (fp == StandardNames.XSL_USE_PACKAGE || fp == StandardNames.XSL_EXPOSE)) {
                // all is well
            } else if (!NamespaceConstant.XSLT.equals(child.getURI()) && !"".equals(child.getURI())) {
                // elements in other namespaces are allowed and ignored
            } else if (child instanceof AbsentExtensionElement && ((StyleElement) child).forwardsCompatibleModeIsEnabled()) {
                // this is OK: an unknown XSLT element is allowed in forwards compatibility mode
            } else if (NamespaceConstant.XSLT.equals(child.getURI())) {
                ((StyleElement) child).compileError("Element " + child.getDisplayName() +
                        " must not appear directly within " + getDisplayName(), "XTSE0010");
            } else {
                ((StyleElement) child).compileError("Element " + child.getDisplayName() +
                        " must not appear directly within " + getDisplayName() +
                        " because it is not in a namespace", "XTSE0130");
            }
        }

    }



}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy