
net.sf.saxon.expr.AdjacentTextNodeMerger Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of saxon-he Show documentation
Show all versions of saxon-he Show documentation
An OSGi bundle for Saxon-HE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 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.expr;
import net.sf.saxon.event.SequenceReceiver;
import net.sf.saxon.expr.instruct.Block;
import net.sf.saxon.expr.instruct.Choose;
import net.sf.saxon.expr.instruct.ValueOf;
import net.sf.saxon.expr.parser.ExpressionVisitor;
import net.sf.saxon.om.AtomicSequence;
import net.sf.saxon.om.Item;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.pattern.NodeKindTest;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.iter.AdjacentTextNodeMergingIterator;
import net.sf.saxon.tree.util.FastStringBuffer;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.Type;
import net.sf.saxon.type.TypeHierarchy;
import net.sf.saxon.value.AtomicValue;
import net.sf.saxon.value.Cardinality;
import java.util.List;
/**
* This class performs the first phase of processing in "constructing simple content":
* it takes an input sequence, eliminates empty text nodes, and combines adjacent text nodes
* into one.
* @since 9.3
*/
public class AdjacentTextNodeMerger extends UnaryExpression {
public AdjacentTextNodeMerger(Expression p0) {
super(p0);
}
/**
* Make an AdjacentTextNodeMerger expression with a given operand, or a simpler equivalent expression if appropriate
* @param base the operand expression
* @return an AdjacentTextNodeMerger or equivalent expression
*/
public static Expression makeAdjacentTextNodeMerger(Expression base) {
if (base instanceof Literal && ((Literal)base).getValue() instanceof AtomicSequence) {
return base;
} else {
return new AdjacentTextNodeMerger(base);
}
}
@Override
public Expression simplify(ExpressionVisitor visitor) throws XPathException {
if (operand instanceof Literal && ((Literal)operand).getValue() instanceof AtomicValue) {
return operand;
} else {
return super.simplify(visitor);
}
}
/*@NotNull*/
@Override
public Expression typeCheck(ExpressionVisitor visitor, ExpressionVisitor.ContextItemType contextItemType) throws XPathException {
Expression e = super.typeCheck(visitor, contextItemType);
if (e != this) {
return e;
}
// This wrapper expression is unnecessary if the base expression cannot return text nodes,
// or if it can return at most one item
TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
if (th.relationship(getBaseExpression().getItemType(th), NodeKindTest.TEXT) == TypeHierarchy.DISJOINT) {
return getBaseExpression();
}
if (!Cardinality.allowsMany(getBaseExpression().getCardinality())) {
return getBaseExpression();
}
// In a choose expression, we can push the wrapper down to the action branches (whence it may disappear)
if (getBaseExpression() instanceof Choose) {
Choose choose = (Choose) getBaseExpression();
Expression[] actions = choose.getActions();
for (int i=0; i 0) {
fsb.append(s);
prevText = true;
}
} else {
if (prevText) {
out.characters(fsb, locationId, options);
}
prevText = false;
fsb.setLength(0);
out.append(item, locationId, options);
}
}
if (prevText) {
out.characters(fsb, locationId, options);
}
}
@Override
public String getExpressionName() {
return "mergeAdjacentText";
}
/**
* Ask whether an item is a text node
* @param item the item in question
* @return true if the item is a node of kind text
*/
public static boolean isTextNode(Item item) {
return item instanceof NodeInfo && ((NodeInfo)item).getNodeKind() == Type.TEXT;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy