dom/xslt/xpath/txMozillaXPathTreeWalker.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "txXPathTreeWalker.h"
     7 #include "nsIAtom.h"
     8 #include "nsIAttribute.h"
     9 #include "nsIDOMAttr.h"
    10 #include "nsIDOMDocument.h"
    11 #include "nsIDOMNode.h"
    12 #include "nsIDOMElement.h"
    13 #include "nsIDOMProcessingInstruction.h"
    14 #include "nsINodeInfo.h"
    15 #include "nsPrintfCString.h"
    16 #include "nsReadableUtils.h"
    17 #include "nsString.h"
    18 #include "nsTextFragment.h"
    19 #include "txXMLUtils.h"
    20 #include "txLog.h"
    21 #include "nsUnicharUtils.h"
    22 #include "nsAttrName.h"
    23 #include "nsTArray.h"
    24 #include "mozilla/dom/Attr.h"
    25 #include "mozilla/dom/Element.h"
    26 #include <stdint.h>
    27 #include <algorithm>
    29 using mozilla::dom::Attr;
    31 const uint32_t kUnknownIndex = uint32_t(-1);
    33 txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
    34     : mPosition(aOther.mPosition),
    35       mCurrentIndex(aOther.mCurrentIndex)
    36 {
    37 }
    39 txXPathTreeWalker::txXPathTreeWalker(const txXPathNode& aNode)
    40     : mPosition(aNode),
    41       mCurrentIndex(kUnknownIndex)
    42 {
    43 }
    45 void
    46 txXPathTreeWalker::moveToRoot()
    47 {
    48     if (mPosition.isDocument()) {
    49         return;
    50     }
    52     nsIDocument* root = mPosition.mNode->GetCurrentDoc();
    53     if (root) {
    54         mPosition.mIndex = txXPathNode::eDocument;
    55         mPosition.mNode = root;
    56     }
    57     else {
    58         nsINode *rootNode = mPosition.Root();
    60         NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
    61                      "root of subtree wasn't an nsIContent");
    63         mPosition.mIndex = txXPathNode::eContent;
    64         mPosition.mNode = rootNode;
    65     }
    67     mCurrentIndex = kUnknownIndex;
    68     mDescendants.Clear();
    69 }
    71 bool
    72 txXPathTreeWalker::moveToElementById(const nsAString& aID)
    73 {
    74     if (aID.IsEmpty()) {
    75         return false;
    76     }
    78     nsIDocument* doc = mPosition.mNode->GetCurrentDoc();
    80     nsCOMPtr<nsIContent> content;
    81     if (doc) {
    82         content = doc->GetElementById(aID);
    83     }
    84     else {
    85         // We're in a disconnected subtree, search only that subtree.
    86         nsINode *rootNode = mPosition.Root();
    88         NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
    89                      "root of subtree wasn't an nsIContent");
    91         content = nsContentUtils::MatchElementId(
    92             static_cast<nsIContent*>(rootNode), aID);
    93     }
    95     if (!content) {
    96         return false;
    97     }
    99     mPosition.mIndex = txXPathNode::eContent;
   100     mPosition.mNode = content;
   101     mCurrentIndex = kUnknownIndex;
   102     mDescendants.Clear();
   104     return true;
   105 }
   107 bool
   108 txXPathTreeWalker::moveToFirstAttribute()
   109 {
   110     if (!mPosition.isContent()) {
   111         return false;
   112     }
   114     return moveToValidAttribute(0);
   115 }
   117 bool
   118 txXPathTreeWalker::moveToNextAttribute()
   119 {
   120     // XXX an assertion should be enough here with the current code
   121     if (!mPosition.isAttribute()) {
   122         return false;
   123     }
   125     return moveToValidAttribute(mPosition.mIndex + 1);
   126 }
   128 bool
   129 txXPathTreeWalker::moveToValidAttribute(uint32_t aStartIndex)
   130 {
   131     NS_ASSERTION(!mPosition.isDocument(), "documents doesn't have attrs");
   133     uint32_t total = mPosition.Content()->GetAttrCount();
   134     if (aStartIndex >= total) {
   135         return false;
   136     }
   138     uint32_t index;
   139     for (index = aStartIndex; index < total; ++index) {
   140         const nsAttrName* name = mPosition.Content()->GetAttrNameAt(index);
   142         // We need to ignore XMLNS attributes.
   143         if (name->NamespaceID() != kNameSpaceID_XMLNS) {
   144             mPosition.mIndex = index;
   146             return true;
   147         }
   148     }
   149     return false;
   150 }
   152 bool
   153 txXPathTreeWalker::moveToNamedAttribute(nsIAtom* aLocalName, int32_t aNSID)
   154 {
   155     if (!mPosition.isContent()) {
   156         return false;
   157     }
   159     const nsAttrName* name;
   160     uint32_t i;
   161     for (i = 0; (name = mPosition.Content()->GetAttrNameAt(i)); ++i) {
   162         if (name->Equals(aLocalName, aNSID)) {
   163             mPosition.mIndex = i;
   165             return true;
   166         }
   167     }
   168     return false;
   169 }
   171 bool
   172 txXPathTreeWalker::moveToFirstChild()
   173 {
   174     if (mPosition.isAttribute()) {
   175         return false;
   176     }
   178     NS_ASSERTION(!mPosition.isDocument() ||
   179                  (mCurrentIndex == kUnknownIndex && mDescendants.IsEmpty()),
   180                  "we shouldn't have any position info at the document");
   181     NS_ASSERTION(mCurrentIndex != kUnknownIndex || mDescendants.IsEmpty(),
   182                  "Index should be known if parents index are");
   184     nsIContent* child = mPosition.mNode->GetFirstChild();
   185     if (!child) {
   186         return false;
   187     }
   188     mPosition.mIndex = txXPathNode::eContent;
   189     mPosition.mNode = child;
   191     if (mCurrentIndex != kUnknownIndex &&
   192         !mDescendants.AppendValue(mCurrentIndex)) {
   193         mDescendants.Clear();
   194     }
   195     mCurrentIndex = 0;
   197     return true;
   198 }
   200 bool
   201 txXPathTreeWalker::moveToLastChild()
   202 {
   203     if (mPosition.isAttribute()) {
   204         return false;
   205     }
   207     NS_ASSERTION(!mPosition.isDocument() ||
   208                  (mCurrentIndex == kUnknownIndex && mDescendants.IsEmpty()),
   209                  "we shouldn't have any position info at the document");
   210     NS_ASSERTION(mCurrentIndex != kUnknownIndex || mDescendants.IsEmpty(),
   211                  "Index should be known if parents index are");
   213     uint32_t total = mPosition.mNode->GetChildCount();
   214     if (!total) {
   215         return false;
   216     }
   217     mPosition.mNode = mPosition.mNode->GetLastChild();
   219     if (mCurrentIndex != kUnknownIndex &&
   220         !mDescendants.AppendValue(mCurrentIndex)) {
   221         mDescendants.Clear();
   222     }
   223     mCurrentIndex = total - 1;
   225     return true;
   226 }
   228 bool
   229 txXPathTreeWalker::moveToNextSibling()
   230 {
   231     if (!mPosition.isContent()) {
   232         return false;
   233     }
   235     return moveToSibling(1);
   236 }
   238 bool
   239 txXPathTreeWalker::moveToPreviousSibling()
   240 {
   241     if (!mPosition.isContent()) {
   242         return false;
   243     }
   245     return moveToSibling(-1);
   246 }
   248 bool
   249 txXPathTreeWalker::moveToParent()
   250 {
   251     if (mPosition.isDocument()) {
   252         return false;
   253     }
   255     if (mPosition.isAttribute()) {
   256         mPosition.mIndex = txXPathNode::eContent;
   258         return true;
   259     }
   261     nsINode* parent = mPosition.mNode->GetParentNode();
   262     if (!parent) {
   263         return false;
   264     }
   266     uint32_t count = mDescendants.Length();
   267     if (count) {
   268         mCurrentIndex = mDescendants.ValueAt(--count);
   269         mDescendants.RemoveValueAt(count);
   270     }
   271     else {
   272         mCurrentIndex = kUnknownIndex;
   273     }
   275     mPosition.mIndex = mPosition.mNode->GetParent() ?
   276       txXPathNode::eContent : txXPathNode::eDocument;
   277     mPosition.mNode = parent;
   279     return true;
   280 }
   282 bool
   283 txXPathTreeWalker::moveToSibling(int32_t aDir)
   284 {
   285     NS_ASSERTION(mPosition.isContent(),
   286                  "moveToSibling should only be called for content");
   288     nsINode* parent = mPosition.mNode->GetParentNode();
   289     if (!parent) {
   290         return false;
   291     }
   292     if (mCurrentIndex == kUnknownIndex) {
   293         mCurrentIndex = parent->IndexOf(mPosition.mNode);
   294     }
   296     // if mCurrentIndex is 0 we rely on GetChildAt returning null for an
   297     // index of uint32_t(-1).
   298     uint32_t newIndex = mCurrentIndex + aDir;
   299     nsIContent* newChild = parent->GetChildAt(newIndex);
   300     if (!newChild) {
   301         return false;
   302     }
   304     mPosition.mNode = newChild;
   305     mCurrentIndex = newIndex;
   307     return true;
   308 }
   310 txXPathNode::txXPathNode(const txXPathNode& aNode)
   311   : mNode(aNode.mNode),
   312     mRefCountRoot(aNode.mRefCountRoot),
   313     mIndex(aNode.mIndex)
   314 {
   315     MOZ_COUNT_CTOR(txXPathNode);
   316     if (mRefCountRoot) {
   317         NS_ADDREF(Root());
   318     }
   319 }
   321 txXPathNode::~txXPathNode()
   322 {
   323     MOZ_COUNT_DTOR(txXPathNode);
   324     if (mRefCountRoot) {
   325         nsINode *root = Root();
   326         NS_RELEASE(root);
   327     }
   328 }
   330 /* static */
   331 bool
   332 txXPathNodeUtils::getAttr(const txXPathNode& aNode, nsIAtom* aLocalName,
   333                           int32_t aNSID, nsAString& aValue)
   334 {
   335     if (aNode.isDocument() || aNode.isAttribute()) {
   336         return false;
   337     }
   339     return aNode.Content()->GetAttr(aNSID, aLocalName, aValue);
   340 }
   342 /* static */
   343 already_AddRefed<nsIAtom>
   344 txXPathNodeUtils::getLocalName(const txXPathNode& aNode)
   345 {
   346     if (aNode.isDocument()) {
   347         return nullptr;
   348     }
   350     if (aNode.isContent()) {
   351         if (aNode.mNode->IsElement()) {
   352             nsCOMPtr<nsIAtom> localName = aNode.Content()->Tag();
   353             return localName.forget();
   354         }
   356         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
   357             nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
   358             nsAutoString target;
   359             node->GetNodeName(target);
   361             return NS_NewAtom(target);
   362         }
   364         return nullptr;
   365     }
   367     nsCOMPtr<nsIAtom> localName = aNode.Content()->
   368         GetAttrNameAt(aNode.mIndex)->LocalName();
   370     return localName.forget();
   371 }
   373 nsIAtom*
   374 txXPathNodeUtils::getPrefix(const txXPathNode& aNode)
   375 {
   376     if (aNode.isDocument()) {
   377         return nullptr;
   378     }
   380     if (aNode.isContent()) {
   381         // All other nsIContent node types but elements have a null prefix
   382         // which is what we want here.
   383         return aNode.Content()->NodeInfo()->GetPrefixAtom();
   384     }
   386     return aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetPrefix();
   387 }
   389 /* static */
   390 void
   391 txXPathNodeUtils::getLocalName(const txXPathNode& aNode, nsAString& aLocalName)
   392 {
   393     if (aNode.isDocument()) {
   394         aLocalName.Truncate();
   396         return;
   397     }
   399     if (aNode.isContent()) {
   400         if (aNode.mNode->IsElement()) {
   401             nsINodeInfo* nodeInfo = aNode.Content()->NodeInfo();
   402             nodeInfo->GetName(aLocalName);
   403             return;
   404         }
   406         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
   407             // PIs don't have a nodeinfo but do have a name
   408             nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
   409             node->GetNodeName(aLocalName);
   411             return;
   412         }
   414         aLocalName.Truncate();
   416         return;
   417     }
   419     aNode.Content()->GetAttrNameAt(aNode.mIndex)->LocalName()->
   420       ToString(aLocalName);
   422     // Check for html
   423     if (aNode.Content()->NodeInfo()->NamespaceEquals(kNameSpaceID_None) &&
   424         aNode.Content()->IsHTML()) {
   425         nsContentUtils::ASCIIToUpper(aLocalName);
   426     }
   427 }
   429 /* static */
   430 void
   431 txXPathNodeUtils::getNodeName(const txXPathNode& aNode, nsAString& aName)
   432 {
   433     if (aNode.isDocument()) {
   434         aName.Truncate();
   436         return;
   437     }
   439     if (aNode.isContent()) {
   440         // Elements and PIs have a name
   441         if (aNode.mNode->IsElement() ||
   442             aNode.mNode->NodeType() ==
   443             nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
   444             aName = aNode.Content()->NodeName();
   445             return;
   446         }
   448         aName.Truncate();
   450         return;
   451     }
   453     aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetQualifiedName(aName);
   454 }
   456 /* static */
   457 int32_t
   458 txXPathNodeUtils::getNamespaceID(const txXPathNode& aNode)
   459 {
   460     if (aNode.isDocument()) {
   461         return kNameSpaceID_None;
   462     }
   464     if (aNode.isContent()) {
   465         return aNode.Content()->GetNameSpaceID();
   466     }
   468     return aNode.Content()->GetAttrNameAt(aNode.mIndex)->NamespaceID();
   469 }
   471 /* static */
   472 void
   473 txXPathNodeUtils::getNamespaceURI(const txXPathNode& aNode, nsAString& aURI)
   474 {
   475     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(getNamespaceID(aNode), aURI);
   476 }
   478 /* static */
   479 uint16_t
   480 txXPathNodeUtils::getNodeType(const txXPathNode& aNode)
   481 {
   482     if (aNode.isDocument()) {
   483         return txXPathNodeType::DOCUMENT_NODE;
   484     }
   486     if (aNode.isContent()) {
   487         return aNode.mNode->NodeType();
   488     }
   490     return txXPathNodeType::ATTRIBUTE_NODE;
   491 }
   493 /* static */
   494 void
   495 txXPathNodeUtils::appendNodeValue(const txXPathNode& aNode, nsAString& aResult)
   496 {
   497     if (aNode.isAttribute()) {
   498         const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
   500         if (aResult.IsEmpty()) {
   501             aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
   502                                      aResult);
   503         }
   504         else {
   505             nsAutoString result;
   506             aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
   507                                      result);
   508             aResult.Append(result);
   509         }
   511         return;
   512     }
   514     if (aNode.isDocument() ||
   515         aNode.mNode->IsElement() ||
   516         aNode.mNode->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT)) {
   517         nsContentUtils::AppendNodeTextContent(aNode.mNode, true, aResult,
   518                                               mozilla::fallible_t());
   520         return;
   521     }
   523     aNode.Content()->AppendTextTo(aResult);
   524 }
   526 /* static */
   527 bool
   528 txXPathNodeUtils::isWhitespace(const txXPathNode& aNode)
   529 {
   530     NS_ASSERTION(aNode.isContent() && isText(aNode), "Wrong type!");
   532     return aNode.Content()->TextIsOnlyWhitespace();
   533 }
   535 /* static */
   536 txXPathNode*
   537 txXPathNodeUtils::getOwnerDocument(const txXPathNode& aNode)
   538 {
   539     return new txXPathNode(aNode.mNode->OwnerDoc());
   540 }
   542 const char gPrintfFmt[] = "id0x%p";
   543 const char gPrintfFmtAttr[] = "id0x%p-%010i";
   545 /* static */
   546 nsresult
   547 txXPathNodeUtils::getXSLTId(const txXPathNode& aNode,
   548                             const txXPathNode& aBase,
   549                             nsAString& aResult)
   550 {
   551     uintptr_t nodeid = ((uintptr_t)aNode.mNode) - ((uintptr_t)aBase.mNode);
   552     if (!aNode.isAttribute()) {
   553         CopyASCIItoUTF16(nsPrintfCString(gPrintfFmt, nodeid),
   554                          aResult);
   555     }
   556     else {
   557         CopyASCIItoUTF16(nsPrintfCString(gPrintfFmtAttr,
   558                                          nodeid, aNode.mIndex), aResult);
   559     }
   561     return NS_OK;
   562 }
   564 /* static */
   565 void
   566 txXPathNodeUtils::getBaseURI(const txXPathNode& aNode, nsAString& aURI)
   567 {
   568     aNode.mNode->GetBaseURI(aURI);
   569 }
   571 /* static */
   572 int
   573 txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
   574                                   const txXPathNode& aOtherNode)
   575 {
   576     // First check for equal nodes or attribute-nodes on the same element.
   577     if (aNode.mNode == aOtherNode.mNode) {
   578         if (aNode.mIndex == aOtherNode.mIndex) {
   579             return 0;
   580         }
   582         NS_ASSERTION(!aNode.isDocument() && !aOtherNode.isDocument(),
   583                      "documents should always have a set index");
   585         if (aNode.isContent() || (!aOtherNode.isContent() &&
   586                                   aNode.mIndex < aOtherNode.mIndex)) {
   587             return -1;
   588         }
   590         return 1;
   591     }
   593     // Get document for both nodes.
   594     nsIDocument* document = aNode.mNode->GetCurrentDoc();
   595     nsIDocument* otherDocument = aOtherNode.mNode->GetCurrentDoc();
   597     // If the nodes have different current documents, compare the document
   598     // pointers.
   599     if (document != otherDocument) {
   600         return document < otherDocument ? -1 : 1;
   601     }
   603     // Now either both nodes are in orphan trees, or they are both in the
   604     // same tree.
   606     // Get parents up the tree.
   607     nsAutoTArray<nsINode*, 8> parents, otherParents;
   608     nsINode* node = aNode.mNode;
   609     nsINode* otherNode = aOtherNode.mNode;
   610     nsINode* parent, *otherParent;
   611     while (node && otherNode) {
   612         parent = node->GetParentNode();
   613         otherParent = otherNode->GetParentNode();
   615         // Hopefully this is a common case.
   616         if (parent == otherParent) {
   617             if (!parent) {
   618                 // Both node and otherNode are root nodes in respective orphan
   619                 // tree.
   620                 return node < otherNode ? -1 : 1;
   621             }
   623             return parent->IndexOf(node) < parent->IndexOf(otherNode) ?
   624                    -1 : 1;
   625         }
   627         parents.AppendElement(node);
   628         otherParents.AppendElement(otherNode);
   629         node = parent;
   630         otherNode = otherParent;
   631     }
   633     while (node) {
   634         parents.AppendElement(node);
   635         node = node->GetParentNode();
   636     }
   637     while (otherNode) {
   638         otherParents.AppendElement(otherNode);
   639         otherNode = otherNode->GetParentNode();
   640     }
   642     // Walk back down along the parent-chains until we find where they split.
   643     int32_t total = parents.Length() - 1;
   644     int32_t otherTotal = otherParents.Length() - 1;
   645     NS_ASSERTION(total != otherTotal, "Can't have same number of parents");
   647     int32_t lastIndex = std::min(total, otherTotal);
   648     int32_t i;
   649     parent = nullptr;
   650     for (i = 0; i <= lastIndex; ++i) {
   651         node = parents.ElementAt(total - i);
   652         otherNode = otherParents.ElementAt(otherTotal - i);
   653         if (node != otherNode) {
   654             if (!parent) {
   655                 // The two nodes are in different orphan subtrees.
   656                 NS_ASSERTION(i == 0, "this shouldn't happen");
   657                 return node < otherNode ? -1 : 1;
   658             }
   660             int32_t index = parent->IndexOf(node);
   661             int32_t otherIndex = parent->IndexOf(otherNode);
   662             NS_ASSERTION(index != otherIndex && index >= 0 && otherIndex >= 0,
   663                          "invalid index in compareTreePosition");
   665             return index < otherIndex ? -1 : 1;
   666         }
   668         parent = node;
   669     }
   671     // One node is a descendant of the other. The one with the shortest
   672     // parent-chain is first in the document.
   673     return total < otherTotal ? -1 : 1;
   674 }
   676 /* static */
   677 txXPathNode*
   678 txXPathNativeNode::createXPathNode(nsIContent* aContent, bool aKeepRootAlive)
   679 {
   680     nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(aContent) : nullptr;
   682     return new txXPathNode(aContent, txXPathNode::eContent, root);
   683 }
   685 /* static */
   686 txXPathNode*
   687 txXPathNativeNode::createXPathNode(nsIDOMNode* aNode, bool aKeepRootAlive)
   688 {
   689     uint16_t nodeType;
   690     aNode->GetNodeType(&nodeType);
   692     if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) {
   693         nsCOMPtr<nsIAttribute> attr = do_QueryInterface(aNode);
   694         NS_ASSERTION(attr, "doesn't implement nsIAttribute");
   696         nsINodeInfo *nodeInfo = attr->NodeInfo();
   697         mozilla::dom::Element* parent =
   698           static_cast<Attr*>(attr.get())->GetElement();
   699         if (!parent) {
   700             return nullptr;
   701         }
   703         nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(parent) : nullptr;
   705         uint32_t i, total = parent->GetAttrCount();
   706         for (i = 0; i < total; ++i) {
   707             const nsAttrName* name = parent->GetAttrNameAt(i);
   708             if (nodeInfo->Equals(name->LocalName(), name->NamespaceID())) {
   709                 return new txXPathNode(parent, i, root);
   710             }
   711         }
   713         NS_ERROR("Couldn't find the attribute in its parent!");
   715         return nullptr;
   716     }
   718     nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   719     uint32_t index;
   720     nsINode* root = aKeepRootAlive ? node.get() : nullptr;
   722     if (nodeType == nsIDOMNode::DOCUMENT_NODE) {
   723         index = txXPathNode::eDocument;
   724     }
   725     else {
   726         index = txXPathNode::eContent;
   727         if (root) {
   728             root = txXPathNode::RootOf(root);
   729         }
   730     }
   732     return new txXPathNode(node, index, root);
   733 }
   735 /* static */
   736 txXPathNode*
   737 txXPathNativeNode::createXPathNode(nsIDOMDocument* aDocument)
   738 {
   739     nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
   740     return new txXPathNode(document);
   741 }
   743 /* static */
   744 nsresult
   745 txXPathNativeNode::getNode(const txXPathNode& aNode, nsIDOMNode** aResult)
   746 {
   747     if (!aNode.isAttribute()) {
   748         return CallQueryInterface(aNode.mNode, aResult);
   749     }
   751     const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
   753     nsAutoString namespaceURI;
   754     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(name->NamespaceID(), namespaceURI);
   756     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode.mNode);
   757     nsCOMPtr<nsIDOMAttr> attr;
   758     element->GetAttributeNodeNS(namespaceURI,
   759                                 nsDependentAtomString(name->LocalName()),
   760                                 getter_AddRefs(attr));
   762     return CallQueryInterface(attr, aResult);
   763 }
   765 /* static */
   766 nsIContent*
   767 txXPathNativeNode::getContent(const txXPathNode& aNode)
   768 {
   769     NS_ASSERTION(aNode.isContent(),
   770                  "Only call getContent on nsIContent wrappers!");
   771     return aNode.Content();
   772 }
   774 /* static */
   775 nsIDocument*
   776 txXPathNativeNode::getDocument(const txXPathNode& aNode)
   777 {
   778     NS_ASSERTION(aNode.isDocument(),
   779                  "Only call getDocument on nsIDocument wrappers!");
   780     return aNode.Document();
   781 }

mercurial