001: package net.sf.saxon.style;
002:
003: import net.sf.saxon.Configuration;
004: import net.sf.saxon.expr.*;
005: import net.sf.saxon.instruct.*;
006: import net.sf.saxon.om.AttributeCollection;
007: import net.sf.saxon.om.Axis;
008: import net.sf.saxon.om.Validation;
009: import net.sf.saxon.pattern.NodeKindTest;
010: import net.sf.saxon.trans.XPathException;
011: import net.sf.saxon.type.SchemaType;
012: import net.sf.saxon.value.EmptySequence;
013: import net.sf.saxon.value.SequenceType;
014:
015: /**
016: * Handler for xsl:copy elements in stylesheet. <br>
017: */
018:
019: public class XSLCopy extends StyleElement {
020:
021: private String use; // value of use-attribute-sets attribute
022: private AttributeSet[] attributeSets = null;
023: private boolean copyNamespaces = true;
024: private boolean inheritNamespaces = true;
025: private int validationAction = Validation.PRESERVE;
026: private SchemaType schemaType = null;
027:
028: /**
029: * Determine whether this node is an instruction.
030: * @return true - it is an instruction
031: */
032:
033: public boolean isInstruction() {
034: return true;
035: }
036:
037: /**
038: * Determine whether this type of element is allowed to contain a template-body
039: * @return true: yes, it may contain a template-body
040: */
041:
042: public boolean mayContainSequenceConstructor() {
043: return true;
044: }
045:
046: public void prepareAttributes() throws XPathException {
047:
048: AttributeCollection atts = getAttributeList();
049: String copyNamespacesAtt = null;
050: String validationAtt = null;
051: String typeAtt = null;
052: String inheritAtt = null;
053:
054: for (int a = 0; a < atts.getLength(); a++) {
055: int nc = atts.getNameCode(a);
056: String f = getNamePool().getClarkName(nc);
057: if (f == StandardNames.USE_ATTRIBUTE_SETS) {
058: use = atts.getValue(a);
059: } else if (f == StandardNames.COPY_NAMESPACES) {
060: copyNamespacesAtt = atts.getValue(a).trim();
061: } else if (f == StandardNames.TYPE) {
062: typeAtt = atts.getValue(a).trim();
063: } else if (f == StandardNames.VALIDATION) {
064: validationAtt = atts.getValue(a).trim();
065: } else if (f == StandardNames.INHERIT_NAMESPACES) {
066: inheritAtt = atts.getValue(a).trim();
067: } else {
068: checkUnknownAttribute(nc);
069: }
070: }
071:
072: if (copyNamespacesAtt == null) {
073: copyNamespaces = true;
074: } else {
075: if (copyNamespacesAtt.equals("yes")) {
076: copyNamespaces = true;
077: } else if (copyNamespacesAtt.equals("no")) {
078: copyNamespaces = false;
079: } else {
080: compileError(
081: "Value of copy-namespaces must be 'yes' or 'no'",
082: "XTSE0020");
083: }
084: }
085:
086: if (typeAtt != null && validationAtt != null) {
087: compileError(
088: "The type and validation attributes must not both be specified",
089: "XTSE1505");
090: }
091:
092: if (validationAtt != null) {
093: validationAction = Validation.getCode(validationAtt);
094: if (validationAction != Validation.STRIP
095: && !getConfiguration().isSchemaAware(
096: Configuration.XSLT)) {
097: compileError(
098: "To perform validation, a schema-aware XSLT processor is needed",
099: "XTSE1660");
100: }
101: } else {
102: validationAction = getContainingStylesheet()
103: .getDefaultValidation();
104: }
105:
106: if (typeAtt != null) {
107: schemaType = getSchemaType(typeAtt);
108: if (!getConfiguration().isSchemaAware(Configuration.XSLT)) {
109: compileError(
110: "The @type attribute is available only with a schema-aware XSLT processor",
111: "XTSE1660");
112: }
113: }
114: if (inheritAtt != null) {
115: if (inheritAtt.equals("yes")) {
116: inheritNamespaces = true;
117: } else if (inheritAtt.equals("no")) {
118: inheritNamespaces = false;
119: } else {
120: compileError(
121: "The @inherit-namespaces attribute has permitted values (yes, no)",
122: "XTSE0020");
123: }
124: }
125:
126: if (validationAction == Validation.PRESERVE && !copyNamespaces) {
127: compileError(
128: "copy-namespaces must be set to 'yes' when validation is set to 'preserve'",
129: "XTSE0950");
130: }
131: }
132:
133: public void validate() throws XPathException {
134: checkWithinTemplate();
135: if (use != null) {
136: attributeSets = getAttributeSets(use, null); // find any referenced attribute sets
137: }
138: }
139:
140: public Expression compile(Executable exec) throws XPathException {
141: Copy inst = new Copy(copyNamespaces, inheritNamespaces,
142: schemaType, validationAction);
143: Expression content = compileSequenceConstructor(exec,
144: iterateAxis(Axis.CHILD), true);
145:
146: if (attributeSets != null) {
147: UseAttributeSets use = new UseAttributeSets(attributeSets);
148: // The use-attribute-sets is ignored unless the context item is an element node. So we
149: // wrap the UseAttributeSets instruction in a conditional to perform a run-time test
150: Expression condition = new InstanceOfExpression(
151: new ContextItemExpression(), SequenceType
152: .makeSequenceType(NodeKindTest.ELEMENT,
153: StaticProperty.EXACTLY_ONE));
154: Expression choice = new IfExpression(condition, use,
155: EmptySequence.getInstance());
156: if (content == null) {
157: content = choice;
158: } else {
159: content = Block.makeBlock(choice, content);
160: if (content instanceof ComputedExpression) {
161: ((ComputedExpression) content)
162: .setLocationId(allocateLocationId(
163: getSystemId(), getLineNumber()));
164: }
165: }
166: }
167:
168: if (content == null) {
169: content = EmptySequence.getInstance();
170: }
171: inst.setContentExpression(content);
172: ExpressionTool.makeParentReferences(inst);
173: return inst;
174: }
175:
176: }
177:
178: //
179: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
180: // you may not use this file except in compliance with the License. You may obtain a copy of the
181: // License at http://www.mozilla.org/MPL/
182: //
183: // Software distributed under the License is distributed on an "AS IS" basis,
184: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
185: // See the License for the specific language governing rights and limitations under the License.
186: //
187: // The Original Code is: all this file.
188: //
189: // The Initial Developer of the Original Code is Michael H. Kay.
190: //
191: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
192: //
193: // Contributor(s): none.
194: //
|