Back to index

lightning-sunbird  0.9+nobinonly
txStandaloneXPathTreeWalker.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is TransforMiiX XSLT processor code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2003
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Peter Van der Beken <peterv@propagandism.org>
00024  *   Axel Hecht <axel@pike.org>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "txXPathTreeWalker.h"
00041 #include "nsPrintfCString.h"
00042 #include "nsReadableUtils.h"
00043 #include "nsString.h"
00044 #include "XMLUtils.h"
00045 
00046 txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
00047     : mPosition(aOther.mPosition)
00048 {
00049 }
00050 
00051 txXPathTreeWalker::txXPathTreeWalker(const txXPathNode& aNode)
00052     : mPosition(aNode)
00053 {
00054 }
00055 
00056 txXPathTreeWalker::~txXPathTreeWalker()
00057 {
00058 }
00059 
00060 #define INNER mPosition.mInner
00061 
00062 PRBool
00063 txXPathTreeWalker::moveToElementById(const nsAString& aID)
00064 {
00065     Document* document;
00066     if (INNER->nodeType == Node::DOCUMENT_NODE) {
00067         document = NS_STATIC_CAST(Document*, INNER);
00068     }
00069     else {
00070         document = INNER->ownerDocument;
00071     }
00072 
00073     Element* element =
00074         document->getElementById(aID);
00075     if (!element) {
00076         return PR_FALSE;
00077     }
00078 
00079     INNER = element;
00080 
00081     return PR_TRUE;
00082 }
00083 
00084 PRBool
00085 txXPathTreeWalker::moveToFirstAttribute()
00086 {
00087     if (INNER->nodeType != Node::ELEMENT_NODE) {
00088         return PR_FALSE;
00089     }
00090 
00091     Element* element = NS_STATIC_CAST(Element*, INNER);
00092     NamedNodeMap* attrs = element->getAttributes();
00093     NodeListDefinition::ListItem* item = attrs->firstItem;
00094     // skip XMLNS attributes
00095     while (item && item->node->getNamespaceID() == kNameSpaceID_XMLNS) {
00096         item = item->next;
00097     }
00098     if (!item) {
00099         return PR_FALSE;
00100     }
00101 
00102     INNER = NS_STATIC_CAST(NodeDefinition*, item->node);
00103     return PR_TRUE;
00104 }
00105 
00106 PRBool
00107 txXPathTreeWalker::moveToNextAttribute()
00108 {
00109     // XXX an assertion should be enough here with the current code
00110     if (INNER->nodeType != Node::ATTRIBUTE_NODE) {
00111         return PR_FALSE;
00112     }
00113 
00114     Node* element = INNER->getXPathParent();
00115     NamedNodeMap* attrs = element->getAttributes();
00116     // find the ListItem for the current Attr
00117     NodeListDefinition::ListItem* item = attrs->firstItem;
00118     while (item->node != INNER) {
00119         item = item->next;
00120     }
00121     NS_ASSERTION(item, "Attr not attribute of it's owner?");
00122     // next item
00123     item = item->next;
00124     // skip XMLNS attributes
00125     while (item && item->node->getNamespaceID() == kNameSpaceID_XMLNS) {
00126         item = item->next;
00127     }
00128     if (!item) {
00129         return PR_FALSE;
00130     }
00131 
00132     INNER = NS_STATIC_CAST(NodeDefinition*, item->node);
00133 
00134     return PR_TRUE;
00135 }
00136 
00137 PRBool
00138 txXPathTreeWalker::moveToFirstChild()
00139 {
00140     if (!INNER->firstChild) {
00141         return PR_FALSE;
00142     }
00143 
00144     INNER = INNER->firstChild;
00145 
00146     return PR_TRUE;
00147 }
00148 
00149 PRBool
00150 txXPathTreeWalker::moveToLastChild()
00151 {
00152     if (!INNER->lastChild) {
00153         return PR_FALSE;
00154     }
00155 
00156     INNER = INNER->lastChild;
00157 
00158     return PR_TRUE;
00159 }
00160 
00161 PRBool
00162 txXPathTreeWalker::moveToNextSibling()
00163 {
00164     if (!INNER->nextSibling) {
00165         return PR_FALSE;
00166     }
00167 
00168     INNER = INNER->nextSibling;
00169 
00170     return PR_TRUE;
00171 }
00172 
00173 PRBool
00174 txXPathTreeWalker::moveToPreviousSibling()
00175 {
00176     if (!INNER->previousSibling) {
00177         return PR_FALSE;
00178     }
00179 
00180     INNER = INNER->previousSibling;
00181 
00182     return PR_TRUE;
00183 }
00184 
00185 PRBool
00186 txXPathTreeWalker::moveToParent()
00187 {
00188     if (INNER->nodeType == Node::ATTRIBUTE_NODE) {
00189         INNER = NS_STATIC_CAST(NodeDefinition*, INNER->getXPathParent());
00190         return PR_TRUE;
00191     }
00192 
00193     if (INNER->nodeType == Node::DOCUMENT_NODE) {
00194         return PR_FALSE;
00195     }
00196 
00197     NS_ASSERTION(INNER->parentNode, "orphaned node shouldn't happen");
00198 
00199     INNER = INNER->parentNode;
00200 
00201     return PR_TRUE;
00202 }
00203 
00204 txXPathNode::txXPathNode(const txXPathNode& aNode)
00205     : mInner(aNode.mInner)
00206 {
00207 }
00208 
00209 PRBool
00210 txXPathNode::operator==(const txXPathNode& aNode) const
00211 {
00212     return (mInner == aNode.mInner);
00213 }
00214 
00215 /* static */
00216 PRBool
00217 txXPathNodeUtils::getAttr(const txXPathNode& aNode, nsIAtom* aLocalName,
00218                           PRInt32 aNSID, nsAString& aValue)
00219 {
00220     if (aNode.mInner->getNodeType() != Node::ELEMENT_NODE) {
00221         return PR_FALSE;
00222     }
00223 
00224     Element* elem = NS_STATIC_CAST(Element*, aNode.mInner);
00225     return elem->getAttr(aLocalName, aNSID, aValue);
00226 }
00227 
00228 /* static */
00229 already_AddRefed<nsIAtom>
00230 txXPathNodeUtils::getLocalName(const txXPathNode& aNode)
00231 {
00232     nsIAtom* localName;
00233     return aNode.mInner->getLocalName(&localName) ? localName : nsnull;
00234 }
00235 
00236 /* static */
00237 void
00238 txXPathNodeUtils::getLocalName(const txXPathNode& aNode, nsAString& aLocalName)
00239 {
00240     nsCOMPtr<nsIAtom> localName;
00241     PRBool hasName = aNode.mInner->getLocalName(getter_AddRefs(localName));
00242     if (hasName && localName) {
00243         localName->ToString(aLocalName);
00244     }
00245 }
00246 
00247 /* static */
00248 void
00249 txXPathNodeUtils::getNodeName(const txXPathNode& aNode, nsAString& aName)
00250 {
00251     aNode.mInner->getNodeName(aName);
00252 }
00253 
00254 /* static */
00255 PRInt32
00256 txXPathNodeUtils::getNamespaceID(const txXPathNode& aNode)
00257 {
00258     return aNode.mInner->getNamespaceID();
00259 }
00260 
00261 /* static */
00262 void
00263 txXPathNodeUtils::getNamespaceURI(const txXPathNode& aNode, nsAString& aURI)
00264 {
00265     aNode.mInner->getNamespaceURI(aURI);
00266 }
00267 
00268 /* static */
00269 PRUint16
00270 txXPathNodeUtils::getNodeType(const txXPathNode& aNode)
00271 {
00272     return aNode.mInner->getNodeType();
00273 }
00274 
00275 /* static */
00276 void
00277 txXPathNodeUtils::appendNodeValueHelper(NodeDefinition* aNode,
00278                                         nsAString& aResult)
00279 {
00280 
00281     NodeDefinition* child = NS_STATIC_CAST(NodeDefinition*,
00282                                            aNode->getFirstChild());
00283     while (child) {
00284         switch (child->getNodeType()) {
00285             case Node::TEXT_NODE:
00286             {
00287                 aResult.Append(child->nodeValue);
00288             }
00289             case Node::ELEMENT_NODE:
00290             {
00291                 appendNodeValueHelper(child, aResult);
00292             }
00293         }
00294         child = NS_STATIC_CAST(NodeDefinition*, child->getNextSibling());
00295     }
00296 }
00297 
00298 /* static */
00299 void
00300 txXPathNodeUtils::appendNodeValue(const txXPathNode& aNode, nsAString& aResult)
00301 {
00302     unsigned short type = aNode.mInner->getNodeType();
00303     if (type == Node::ATTRIBUTE_NODE ||
00304         type == Node::COMMENT_NODE ||
00305         type == Node::PROCESSING_INSTRUCTION_NODE ||
00306         type == Node::TEXT_NODE) {
00307         aResult.Append(aNode.mInner->nodeValue);
00308 
00309         return;
00310     }
00311 
00312     NS_ASSERTION(type == Node::ELEMENT_NODE || type == Node::DOCUMENT_NODE,
00313                  "Element or Document expected");
00314 
00315     appendNodeValueHelper(aNode.mInner, aResult);
00316 }
00317 
00318 /* static */
00319 PRBool
00320 txXPathNodeUtils::isWhitespace(const txXPathNode& aNode)
00321 {
00322     NS_ASSERTION(aNode.mInner->nodeType == Node::TEXT_NODE, "Wrong type!");
00323 
00324     return XMLUtils::isWhitespace(aNode.mInner->nodeValue);
00325 }
00326 
00327 /* static */
00328 txXPathNode*
00329 txXPathNodeUtils::getDocument(const txXPathNode& aNode)
00330 {
00331     if (aNode.mInner->nodeType == Node::DOCUMENT_NODE) {
00332         return new txXPathNode(aNode);
00333     }
00334 
00335     return new txXPathNode(aNode.mInner->ownerDocument);
00336 }
00337 
00338 /* static */
00339 txXPathNode*
00340 txXPathNodeUtils::getOwnerDocument(const txXPathNode& aNode)
00341 {
00342     return getDocument(aNode);
00343 }
00344 
00345 #ifndef HAVE_64BIT_OS
00346 #define kFmtSize 13
00347 const char gPrintfFmt[] = "id0x%08p";
00348 #else
00349 #define kFmtSize 21
00350 const char gPrintfFmt[] = "id0x%016p";
00351 #endif
00352 
00353 /* static */
00354 nsresult
00355 txXPathNodeUtils::getXSLTId(const txXPathNode& aNode,
00356                             nsAString& aResult)
00357 {
00358     CopyASCIItoUCS2(nsPrintfCString(kFmtSize, gPrintfFmt, aNode.mInner),
00359                     aResult);
00360 
00361     return NS_OK;
00362 }
00363 
00364 /* static */
00365 void
00366 txXPathNodeUtils::getBaseURI(const txXPathNode& aNode, nsAString& aURI)
00367 {
00368     aNode.mInner->getBaseURI(aURI);
00369 }
00370 
00371 /* static */
00372 PRIntn
00373 txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
00374                                   const txXPathNode& aOtherNode)
00375 {
00376     // First check for equal nodes.
00377     if (aNode == aOtherNode) {
00378         return 0;
00379     }
00380     return aNode.mInner->compareDocumentPosition(aOtherNode.mInner);
00381 }
00382 
00383 /* static */
00384 txXPathNode*
00385 txXPathNativeNode::createXPathNode(Node* aNode)
00386 {
00387     if (aNode != nsnull) {
00388         return new txXPathNode(NS_STATIC_CAST(NodeDefinition*, aNode));
00389     }
00390     return nsnull;
00391 }
00392 
00393 /* static */
00394 nsresult
00395 txXPathNativeNode::getElement(const txXPathNode& aNode, Element** aResult)
00396 {
00397     if (aNode.mInner->getNodeType() != Node::ELEMENT_NODE) {
00398         return NS_ERROR_FAILURE;
00399     }
00400 
00401     *aResult = NS_STATIC_CAST(Element*, aNode.mInner);
00402 
00403     return NS_OK;
00404 
00405 }
00406 
00407 /* static */
00408 nsresult
00409 txXPathNativeNode::getDocument(const txXPathNode& aNode, Document** aResult)
00410 {
00411     if (aNode.mInner->getNodeType() != Node::DOCUMENT_NODE) {
00412         return NS_ERROR_FAILURE;
00413     }
00414 
00415     *aResult = NS_STATIC_CAST(Document*, aNode.mInner);
00416 
00417     return NS_OK;
00418 }