📄 xnodeset.java
字号:
/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: XNodeSet.java,v 1.2.4.2 2005/09/14 20:34:45 jeffsuttor Exp $ */package com.sun.org.apache.xpath.internal.objects;import com.sun.org.apache.xml.internal.dtm.DTM;import com.sun.org.apache.xml.internal.dtm.DTMIterator;import com.sun.org.apache.xml.internal.dtm.DTMManager;import com.sun.org.apache.xml.internal.utils.XMLString;import com.sun.org.apache.xpath.internal.NodeSetDTM;import com.sun.org.apache.xpath.internal.axes.NodeSequence;import org.w3c.dom.NodeList;import org.w3c.dom.traversal.NodeIterator;/** * This class represents an XPath nodeset object, and is capable of * converting the nodeset to other types, such as a string. * @xsl.usage general */public class XNodeSet extends NodeSequence{ static final long serialVersionUID = 1916026368035639667L; /** * Default constructor for derived objects. */ protected XNodeSet() { } /** * Construct a XNodeSet object. * * @param val Value of the XNodeSet object */ public XNodeSet(DTMIterator val) { super(); if(val instanceof XNodeSet) { setIter(((XNodeSet)val).m_iter); m_dtmMgr = ((XNodeSet)val).m_dtmMgr; m_last = ((XNodeSet)val).m_last; if(!((XNodeSet)val).hasCache()) ((XNodeSet)val).setShouldCacheNodes(true); m_obj = ((XNodeSet)val).m_obj; } else setIter(val); } /** * Construct a XNodeSet object. * * @param val Value of the XNodeSet object */ public XNodeSet(XNodeSet val) { super(); setIter(val.m_iter); m_dtmMgr = val.m_dtmMgr; m_last = val.m_last; if(!val.hasCache()) val.setShouldCacheNodes(true); m_obj = val.m_obj; } /** * Construct an empty XNodeSet object. This is used to create a mutable * nodeset to which random nodes may be added. */ public XNodeSet(DTMManager dtmMgr) { this(DTM.NULL,dtmMgr); } /** * Construct a XNodeSet object for one node. * * @param n Node to add to the new XNodeSet object */ public XNodeSet(int n, DTMManager dtmMgr) { super(new NodeSetDTM(dtmMgr)); m_dtmMgr = dtmMgr; if (DTM.NULL != n) { ((NodeSetDTM) m_obj).addNode(n); m_last = 1; } else m_last = 0; } /** * Tell that this is a CLASS_NODESET. * * @return type CLASS_NODESET */ public int getType() { return CLASS_NODESET; } /** * Given a request type, return the equivalent string. * For diagnostic purposes. * * @return type string "#NODESET" */ public String getTypeString() { return "#NODESET"; } /** * Get numeric value of the string conversion from a single node. * * @param n Node to convert * * @return numeric value of the string conversion from a single node. */ public double getNumberFromNode(int n) { XMLString xstr = m_dtmMgr.getDTM(n).getStringValue(n); return xstr.toDouble(); } /** * Cast result object to a number. * * @return numeric value of the string conversion from the * next node in the NodeSetDTM, or NAN if no node was found */ public double num() { int node = item(0); return (node != DTM.NULL) ? getNumberFromNode(node) : Double.NaN; } /** * Cast result object to a number, but allow side effects, such as the * incrementing of an iterator. * * @return numeric value of the string conversion from the * next node in the NodeSetDTM, or NAN if no node was found */ public double numWithSideEffects() { int node = nextNode(); return (node != DTM.NULL) ? getNumberFromNode(node) : Double.NaN; } /** * Cast result object to a boolean. * * @return True if there is a next node in the nodeset */ public boolean bool() { return (item(0) != DTM.NULL); } /** * Cast result object to a boolean, but allow side effects, such as the * incrementing of an iterator. * * @return True if there is a next node in the nodeset */ public boolean boolWithSideEffects() { return (nextNode() != DTM.NULL); } /** * Get the string conversion from a single node. * * @param n Node to convert * * @return the string conversion from a single node. */ public XMLString getStringFromNode(int n) { // %OPT% // I guess we'll have to get a static instance of the DTM manager... if(DTM.NULL != n) { return m_dtmMgr.getDTM(n).getStringValue(n); } else { return com.sun.org.apache.xpath.internal.objects.XString.EMPTYSTRING; } } /** * Directly call the * characters method on the passed ContentHandler for the * string-value. Multiple calls to the * ContentHandler's characters methods may well occur for a single call to * this method. * * @param ch A non-null reference to a ContentHandler. * * @throws org.xml.sax.SAXException */ public void dispatchCharactersEvents(org.xml.sax.ContentHandler ch) throws org.xml.sax.SAXException { int node = item(0); if(node != DTM.NULL) { m_dtmMgr.getDTM(node).dispatchCharactersEvents(node, ch, false); } } /** * Cast result object to an XMLString. * * @return The document fragment node data or the empty string. */ public XMLString xstr() { int node = item(0); return (node != DTM.NULL) ? getStringFromNode(node) : XString.EMPTYSTRING; } /** * Cast result object to a string. * * @return The string this wraps or the empty string if null */ public void appendToFsb(com.sun.org.apache.xml.internal.utils.FastStringBuffer fsb) { XString xstring = (XString)xstr(); xstring.appendToFsb(fsb); } /** * Cast result object to a string. * * @return the string conversion from the next node in the nodeset * or "" if there is no next node */ public String str() { int node = item(0); return (node != DTM.NULL) ? getStringFromNode(node).toString() : ""; } /** * Return a java object that's closest to the representation * that should be handed to an extension. * * @return The object that this class wraps */ public Object object() { if(null == m_obj) return this; else return m_obj; } // %REVIEW% // hmmm...// /**// * Cast result object to a result tree fragment.// *// * @param support The XPath context to use for the conversion // *// * @return the nodeset as a result tree fragment.// */// public DocumentFragment rtree(XPathContext support)// {// DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();// DocumentBuilder db = dbf.newDocumentBuilder();// Document myDoc = db.newDocument();// // DocumentFragment docFrag = myDoc.createDocumentFragment();//// DTMIterator nl = iter();// int node;//// while (DTM.NULL != (node = nl.nextNode()))// {// frag.appendChild(node, true, true);// }//// return frag.getDocument();// } /** * Cast result object to a nodelist. * * @return a NodeIterator. * * @throws javax.xml.transform.TransformerException */ public NodeIterator nodeset() throws javax.xml.transform.TransformerException { return new com.sun.org.apache.xml.internal.dtm.ref.DTMNodeIterator(iter()); } /** * Cast result object to a nodelist. * * @return a NodeList. * * @throws javax.xml.transform.TransformerException */ public NodeList nodelist() throws javax.xml.transform.TransformerException { com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList nodelist = new com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList(this); // Creating a DTMNodeList has the side-effect that it will create a clone // XNodeSet with cache and run m_iter to the end. You cannot get any node // from m_iter after this call. As a fix, we call SetVector() on the clone's // cache. See Bugzilla 14406. XNodeSet clone = (XNodeSet)nodelist.getDTMIterator(); SetVector(clone.getVector()); return nodelist; } // /**// * Return a java object that's closest to the representation// * that should be handed to an extension.// *// * @return The object that this class wraps// */// public Object object()// {// return new com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList(iter());// } /** * Return the iterator without cloning, etc. */ public DTMIterator iterRaw() { return this; } public void release(DTMIterator iter) { } /** * Cast result object to a nodelist. * * @return The nodeset as a nodelist */ public DTMIterator iter() { try { if(hasCache()) return cloneWithReset(); else return this; // don't bother to clone... won't do any good! } catch (CloneNotSupportedException cnse) { throw new RuntimeException(cnse.getMessage()); } } /** * Get a fresh copy of the object. For use with variables. * * @return A fresh nodelist. */ public XObject getFresh() { try { if(hasCache()) return (XObject)cloneWithReset(); else return this; // don't bother to clone... won't do any good! } catch (CloneNotSupportedException cnse) { throw new RuntimeException(cnse.getMessage()); } } /** * Cast result object to a mutableNodeset. * * @return The nodeset as a mutableNodeset */ public NodeSetDTM mutableNodeset() { NodeSetDTM mnl; if(m_obj instanceof NodeSetDTM) { mnl = (NodeSetDTM) m_obj; } else { mnl = new NodeSetDTM(iter()); m_obj = mnl; setCurrentPos(0); } return mnl; } /** Less than comparator */ static final LessThanComparator S_LT = new LessThanComparator(); /** Less than or equal comparator */ static final LessThanOrEqualComparator S_LTE = new LessThanOrEqualComparator(); /** Greater than comparator */ static final GreaterThanComparator S_GT = new GreaterThanComparator(); /** Greater than or equal comparator */ static final GreaterThanOrEqualComparator S_GTE = new GreaterThanOrEqualComparator(); /** Equal comparator */ static final EqualComparator S_EQ = new EqualComparator(); /** Not equal comparator */ static final NotEqualComparator S_NEQ = new NotEqualComparator(); /** * Tell if one object is less than the other. * * @param obj2 Object to compare this nodeset to * @param comparator Comparator to use * * @return See the comments below for each object type comparison * * @throws javax.xml.transform.TransformerException */ public boolean compare(XObject obj2, Comparator comparator) throws javax.xml.transform.TransformerException { boolean result = false; int type = obj2.getType(); if (XObject.CLASS_NODESET == type) { // %OPT% This should be XMLString based instead of string based... // From http://www.w3.org/TR/xpath: // If both objects to be compared are node-sets, then the comparison // will be true if and only if there is a node in the first node-set // and a node in the second node-set such that the result of performing // the comparison on the string-values of the two nodes is true. // Note this little gem from the draft: // NOTE: If $x is bound to a node-set, then $x="foo"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -