Line data Source code
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/. */
5 :
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 "nsPrintfCString.h"
15 : #include "nsReadableUtils.h"
16 : #include "nsString.h"
17 : #include "nsTextFragment.h"
18 : #include "txXMLUtils.h"
19 : #include "txLog.h"
20 : #include "nsUnicharUtils.h"
21 : #include "nsAttrName.h"
22 : #include "nsTArray.h"
23 : #include "mozilla/dom/Attr.h"
24 : #include "mozilla/dom/Element.h"
25 : #include <stdint.h>
26 : #include <algorithm>
27 :
28 : using namespace mozilla::dom;
29 :
30 0 : txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
31 0 : : mPosition(aOther.mPosition)
32 : {
33 0 : }
34 :
35 0 : txXPathTreeWalker::txXPathTreeWalker(const txXPathNode& aNode)
36 0 : : mPosition(aNode)
37 : {
38 0 : }
39 :
40 : void
41 0 : txXPathTreeWalker::moveToRoot()
42 : {
43 0 : if (mPosition.isDocument()) {
44 0 : return;
45 : }
46 :
47 0 : nsIDocument* root = mPosition.mNode->GetUncomposedDoc();
48 0 : if (root) {
49 0 : mPosition.mIndex = txXPathNode::eDocument;
50 0 : mPosition.mNode = root;
51 : }
52 : else {
53 0 : nsINode *rootNode = mPosition.Root();
54 :
55 0 : NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
56 : "root of subtree wasn't an nsIContent");
57 :
58 0 : mPosition.mIndex = txXPathNode::eContent;
59 0 : mPosition.mNode = rootNode;
60 : }
61 : }
62 :
63 : bool
64 0 : txXPathTreeWalker::moveToElementById(const nsAString& aID)
65 : {
66 0 : if (aID.IsEmpty()) {
67 0 : return false;
68 : }
69 :
70 0 : nsIDocument* doc = mPosition.mNode->GetUncomposedDoc();
71 :
72 0 : nsCOMPtr<nsIContent> content;
73 0 : if (doc) {
74 0 : content = doc->GetElementById(aID);
75 : }
76 : else {
77 : // We're in a disconnected subtree, search only that subtree.
78 0 : nsINode *rootNode = mPosition.Root();
79 :
80 0 : NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
81 : "root of subtree wasn't an nsIContent");
82 :
83 0 : content = nsContentUtils::MatchElementId(
84 0 : static_cast<nsIContent*>(rootNode), aID);
85 : }
86 :
87 0 : if (!content) {
88 0 : return false;
89 : }
90 :
91 0 : mPosition.mIndex = txXPathNode::eContent;
92 0 : mPosition.mNode = content;
93 :
94 0 : return true;
95 : }
96 :
97 : bool
98 0 : txXPathTreeWalker::moveToFirstAttribute()
99 : {
100 0 : if (!mPosition.isContent()) {
101 0 : return false;
102 : }
103 :
104 0 : return moveToValidAttribute(0);
105 : }
106 :
107 : bool
108 0 : txXPathTreeWalker::moveToNextAttribute()
109 : {
110 : // XXX an assertion should be enough here with the current code
111 0 : if (!mPosition.isAttribute()) {
112 0 : return false;
113 : }
114 :
115 0 : return moveToValidAttribute(mPosition.mIndex + 1);
116 : }
117 :
118 : bool
119 0 : txXPathTreeWalker::moveToValidAttribute(uint32_t aStartIndex)
120 : {
121 0 : NS_ASSERTION(!mPosition.isDocument(), "documents doesn't have attrs");
122 :
123 0 : uint32_t total = mPosition.Content()->GetAttrCount();
124 0 : if (aStartIndex >= total) {
125 0 : return false;
126 : }
127 :
128 : uint32_t index;
129 0 : for (index = aStartIndex; index < total; ++index) {
130 0 : const nsAttrName* name = mPosition.Content()->GetAttrNameAt(index);
131 :
132 : // We need to ignore XMLNS attributes.
133 0 : if (name->NamespaceID() != kNameSpaceID_XMLNS) {
134 0 : mPosition.mIndex = index;
135 :
136 0 : return true;
137 : }
138 : }
139 0 : return false;
140 : }
141 :
142 : bool
143 0 : txXPathTreeWalker::moveToNamedAttribute(nsIAtom* aLocalName, int32_t aNSID)
144 : {
145 0 : if (!mPosition.isContent()) {
146 0 : return false;
147 : }
148 :
149 : const nsAttrName* name;
150 : uint32_t i;
151 0 : for (i = 0; (name = mPosition.Content()->GetAttrNameAt(i)); ++i) {
152 0 : if (name->Equals(aLocalName, aNSID)) {
153 0 : mPosition.mIndex = i;
154 :
155 0 : return true;
156 : }
157 : }
158 0 : return false;
159 : }
160 :
161 : bool
162 0 : txXPathTreeWalker::moveToFirstChild()
163 : {
164 0 : if (mPosition.isAttribute()) {
165 0 : return false;
166 : }
167 :
168 0 : nsIContent* child = mPosition.mNode->GetFirstChild();
169 0 : if (!child) {
170 0 : return false;
171 : }
172 0 : mPosition.mIndex = txXPathNode::eContent;
173 0 : mPosition.mNode = child;
174 :
175 0 : return true;
176 : }
177 :
178 : bool
179 0 : txXPathTreeWalker::moveToLastChild()
180 : {
181 0 : if (mPosition.isAttribute()) {
182 0 : return false;
183 : }
184 :
185 0 : nsIContent* child = mPosition.mNode->GetLastChild();
186 0 : if (!child) {
187 0 : return false;
188 : }
189 :
190 0 : mPosition.mIndex = txXPathNode::eContent;
191 0 : mPosition.mNode = child;
192 :
193 0 : return true;
194 : }
195 :
196 : bool
197 0 : txXPathTreeWalker::moveToNextSibling()
198 : {
199 0 : if (!mPosition.isContent()) {
200 0 : return false;
201 : }
202 :
203 0 : nsINode* sibling = mPosition.mNode->GetNextSibling();
204 0 : if (!sibling) {
205 0 : return false;
206 : }
207 :
208 0 : mPosition.mNode = sibling;
209 :
210 0 : return true;
211 : }
212 :
213 : bool
214 0 : txXPathTreeWalker::moveToPreviousSibling()
215 : {
216 0 : if (!mPosition.isContent()) {
217 0 : return false;
218 : }
219 :
220 0 : nsINode* sibling = mPosition.mNode->GetPreviousSibling();
221 0 : if (!sibling) {
222 0 : return false;
223 : }
224 :
225 0 : mPosition.mNode = sibling;
226 :
227 0 : return true;
228 : }
229 :
230 : bool
231 0 : txXPathTreeWalker::moveToParent()
232 : {
233 0 : if (mPosition.isDocument()) {
234 0 : return false;
235 : }
236 :
237 0 : if (mPosition.isAttribute()) {
238 0 : mPosition.mIndex = txXPathNode::eContent;
239 :
240 0 : return true;
241 : }
242 :
243 0 : nsINode* parent = mPosition.mNode->GetParentNode();
244 0 : if (!parent) {
245 0 : return false;
246 : }
247 :
248 0 : mPosition.mIndex = mPosition.mNode->GetParent() ?
249 : txXPathNode::eContent : txXPathNode::eDocument;
250 0 : mPosition.mNode = parent;
251 :
252 0 : return true;
253 : }
254 :
255 0 : txXPathNode::txXPathNode(const txXPathNode& aNode)
256 0 : : mNode(aNode.mNode),
257 0 : mRefCountRoot(aNode.mRefCountRoot),
258 0 : mIndex(aNode.mIndex)
259 : {
260 0 : MOZ_COUNT_CTOR(txXPathNode);
261 0 : if (mRefCountRoot) {
262 0 : NS_ADDREF(Root());
263 : }
264 0 : }
265 :
266 0 : txXPathNode::~txXPathNode()
267 : {
268 0 : MOZ_COUNT_DTOR(txXPathNode);
269 0 : if (mRefCountRoot) {
270 0 : nsINode *root = Root();
271 0 : NS_RELEASE(root);
272 : }
273 0 : }
274 :
275 : /* static */
276 : bool
277 0 : txXPathNodeUtils::getAttr(const txXPathNode& aNode, nsIAtom* aLocalName,
278 : int32_t aNSID, nsAString& aValue)
279 : {
280 0 : if (aNode.isDocument() || aNode.isAttribute()) {
281 0 : return false;
282 : }
283 :
284 0 : return aNode.Content()->GetAttr(aNSID, aLocalName, aValue);
285 : }
286 :
287 : /* static */
288 : already_AddRefed<nsIAtom>
289 0 : txXPathNodeUtils::getLocalName(const txXPathNode& aNode)
290 : {
291 0 : if (aNode.isDocument()) {
292 0 : return nullptr;
293 : }
294 :
295 0 : if (aNode.isContent()) {
296 0 : if (aNode.mNode->IsElement()) {
297 : nsCOMPtr<nsIAtom> localName =
298 0 : aNode.Content()->NodeInfo()->NameAtom();
299 0 : return localName.forget();
300 : }
301 :
302 0 : if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
303 0 : nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
304 0 : nsAutoString target;
305 0 : node->GetNodeName(target);
306 :
307 0 : return NS_Atomize(target);
308 : }
309 :
310 0 : return nullptr;
311 : }
312 :
313 0 : nsCOMPtr<nsIAtom> localName = aNode.Content()->
314 0 : GetAttrNameAt(aNode.mIndex)->LocalName();
315 :
316 0 : return localName.forget();
317 : }
318 :
319 : nsIAtom*
320 0 : txXPathNodeUtils::getPrefix(const txXPathNode& aNode)
321 : {
322 0 : if (aNode.isDocument()) {
323 0 : return nullptr;
324 : }
325 :
326 0 : if (aNode.isContent()) {
327 : // All other nsIContent node types but elements have a null prefix
328 : // which is what we want here.
329 0 : return aNode.Content()->NodeInfo()->GetPrefixAtom();
330 : }
331 :
332 0 : return aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetPrefix();
333 : }
334 :
335 : /* static */
336 : void
337 0 : txXPathNodeUtils::getLocalName(const txXPathNode& aNode, nsAString& aLocalName)
338 : {
339 0 : if (aNode.isDocument()) {
340 0 : aLocalName.Truncate();
341 :
342 0 : return;
343 : }
344 :
345 0 : if (aNode.isContent()) {
346 0 : if (aNode.mNode->IsElement()) {
347 0 : mozilla::dom::NodeInfo* nodeInfo = aNode.Content()->NodeInfo();
348 0 : nodeInfo->GetName(aLocalName);
349 0 : return;
350 : }
351 :
352 0 : if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
353 : // PIs don't have a nodeinfo but do have a name
354 0 : nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
355 0 : node->GetNodeName(aLocalName);
356 :
357 0 : return;
358 : }
359 :
360 0 : aLocalName.Truncate();
361 :
362 0 : return;
363 : }
364 :
365 0 : aNode.Content()->GetAttrNameAt(aNode.mIndex)->LocalName()->
366 0 : ToString(aLocalName);
367 :
368 : // Check for html
369 0 : if (aNode.Content()->NodeInfo()->NamespaceEquals(kNameSpaceID_None) &&
370 0 : aNode.Content()->IsHTMLElement()) {
371 0 : nsContentUtils::ASCIIToUpper(aLocalName);
372 : }
373 : }
374 :
375 : /* static */
376 : void
377 0 : txXPathNodeUtils::getNodeName(const txXPathNode& aNode, nsAString& aName)
378 : {
379 0 : if (aNode.isDocument()) {
380 0 : aName.Truncate();
381 :
382 0 : return;
383 : }
384 :
385 0 : if (aNode.isContent()) {
386 : // Elements and PIs have a name
387 0 : if (aNode.mNode->IsElement() ||
388 0 : aNode.mNode->NodeType() ==
389 : nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
390 0 : aName = aNode.Content()->NodeName();
391 0 : return;
392 : }
393 :
394 0 : aName.Truncate();
395 :
396 0 : return;
397 : }
398 :
399 0 : aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetQualifiedName(aName);
400 : }
401 :
402 : /* static */
403 : int32_t
404 0 : txXPathNodeUtils::getNamespaceID(const txXPathNode& aNode)
405 : {
406 0 : if (aNode.isDocument()) {
407 0 : return kNameSpaceID_None;
408 : }
409 :
410 0 : if (aNode.isContent()) {
411 0 : return aNode.Content()->GetNameSpaceID();
412 : }
413 :
414 0 : return aNode.Content()->GetAttrNameAt(aNode.mIndex)->NamespaceID();
415 : }
416 :
417 : /* static */
418 : void
419 0 : txXPathNodeUtils::getNamespaceURI(const txXPathNode& aNode, nsAString& aURI)
420 : {
421 0 : nsContentUtils::NameSpaceManager()->GetNameSpaceURI(getNamespaceID(aNode), aURI);
422 0 : }
423 :
424 : /* static */
425 : uint16_t
426 0 : txXPathNodeUtils::getNodeType(const txXPathNode& aNode)
427 : {
428 0 : if (aNode.isDocument()) {
429 0 : return txXPathNodeType::DOCUMENT_NODE;
430 : }
431 :
432 0 : if (aNode.isContent()) {
433 0 : return aNode.mNode->NodeType();
434 : }
435 :
436 0 : return txXPathNodeType::ATTRIBUTE_NODE;
437 : }
438 :
439 : /* static */
440 : void
441 0 : txXPathNodeUtils::appendNodeValue(const txXPathNode& aNode, nsAString& aResult)
442 : {
443 0 : if (aNode.isAttribute()) {
444 0 : const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
445 :
446 0 : if (aResult.IsEmpty()) {
447 0 : aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
448 0 : aResult);
449 : }
450 : else {
451 0 : nsAutoString result;
452 0 : aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
453 0 : result);
454 0 : aResult.Append(result);
455 : }
456 :
457 0 : return;
458 : }
459 :
460 0 : if (aNode.isDocument() ||
461 0 : aNode.mNode->IsElement() ||
462 0 : aNode.mNode->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT)) {
463 0 : nsContentUtils::AppendNodeTextContent(aNode.mNode, true, aResult,
464 0 : mozilla::fallible);
465 :
466 0 : return;
467 : }
468 :
469 0 : aNode.Content()->AppendTextTo(aResult);
470 : }
471 :
472 : /* static */
473 : bool
474 0 : txXPathNodeUtils::isWhitespace(const txXPathNode& aNode)
475 : {
476 0 : NS_ASSERTION(aNode.isContent() && isText(aNode), "Wrong type!");
477 :
478 0 : return aNode.Content()->TextIsOnlyWhitespace();
479 : }
480 :
481 : /* static */
482 : txXPathNode*
483 0 : txXPathNodeUtils::getOwnerDocument(const txXPathNode& aNode)
484 : {
485 0 : return new txXPathNode(aNode.mNode->OwnerDoc());
486 : }
487 :
488 : const char gPrintfFmt[] = "id0x%" PRIxPTR;
489 : const char gPrintfFmtAttr[] = "id0x%" PRIxPTR "-%010i";
490 :
491 : /* static */
492 : nsresult
493 0 : txXPathNodeUtils::getXSLTId(const txXPathNode& aNode,
494 : const txXPathNode& aBase,
495 : nsAString& aResult)
496 : {
497 0 : uintptr_t nodeid = ((uintptr_t)aNode.mNode) - ((uintptr_t)aBase.mNode);
498 0 : if (!aNode.isAttribute()) {
499 0 : CopyASCIItoUTF16(nsPrintfCString(gPrintfFmt, nodeid),
500 0 : aResult);
501 : }
502 : else {
503 0 : CopyASCIItoUTF16(nsPrintfCString(gPrintfFmtAttr,
504 0 : nodeid, aNode.mIndex), aResult);
505 : }
506 :
507 0 : return NS_OK;
508 : }
509 :
510 : /* static */
511 : nsresult
512 0 : txXPathNodeUtils::getBaseURI(const txXPathNode& aNode, nsAString& aURI)
513 : {
514 0 : return aNode.mNode->GetBaseURI(aURI);
515 : }
516 :
517 : /* static */
518 : int
519 0 : txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
520 : const txXPathNode& aOtherNode)
521 : {
522 : // First check for equal nodes or attribute-nodes on the same element.
523 0 : if (aNode.mNode == aOtherNode.mNode) {
524 0 : if (aNode.mIndex == aOtherNode.mIndex) {
525 0 : return 0;
526 : }
527 :
528 0 : NS_ASSERTION(!aNode.isDocument() && !aOtherNode.isDocument(),
529 : "documents should always have a set index");
530 :
531 0 : if (aNode.isContent() || (!aOtherNode.isContent() &&
532 0 : aNode.mIndex < aOtherNode.mIndex)) {
533 0 : return -1;
534 : }
535 :
536 0 : return 1;
537 : }
538 :
539 : // Get document for both nodes.
540 0 : nsIDocument* document = aNode.mNode->GetUncomposedDoc();
541 0 : nsIDocument* otherDocument = aOtherNode.mNode->GetUncomposedDoc();
542 :
543 : // If the nodes have different current documents, compare the document
544 : // pointers.
545 0 : if (document != otherDocument) {
546 0 : return document < otherDocument ? -1 : 1;
547 : }
548 :
549 : // Now either both nodes are in orphan trees, or they are both in the
550 : // same tree.
551 :
552 : // Get parents up the tree.
553 0 : AutoTArray<nsINode*, 8> parents, otherParents;
554 0 : nsINode* node = aNode.mNode;
555 0 : nsINode* otherNode = aOtherNode.mNode;
556 : nsINode* parent;
557 : nsINode* otherParent;
558 0 : while (node && otherNode) {
559 0 : parent = node->GetParentNode();
560 0 : otherParent = otherNode->GetParentNode();
561 :
562 : // Hopefully this is a common case.
563 0 : if (parent == otherParent) {
564 0 : if (!parent) {
565 : // Both node and otherNode are root nodes in respective orphan
566 : // tree.
567 0 : return node < otherNode ? -1 : 1;
568 : }
569 :
570 0 : return parent->IndexOf(node) < parent->IndexOf(otherNode) ?
571 0 : -1 : 1;
572 : }
573 :
574 0 : parents.AppendElement(node);
575 0 : otherParents.AppendElement(otherNode);
576 0 : node = parent;
577 0 : otherNode = otherParent;
578 : }
579 :
580 0 : while (node) {
581 0 : parents.AppendElement(node);
582 0 : node = node->GetParentNode();
583 : }
584 0 : while (otherNode) {
585 0 : otherParents.AppendElement(otherNode);
586 0 : otherNode = otherNode->GetParentNode();
587 : }
588 :
589 : // Walk back down along the parent-chains until we find where they split.
590 0 : int32_t total = parents.Length() - 1;
591 0 : int32_t otherTotal = otherParents.Length() - 1;
592 0 : NS_ASSERTION(total != otherTotal, "Can't have same number of parents");
593 :
594 0 : int32_t lastIndex = std::min(total, otherTotal);
595 : int32_t i;
596 0 : parent = nullptr;
597 0 : for (i = 0; i <= lastIndex; ++i) {
598 0 : node = parents.ElementAt(total - i);
599 0 : otherNode = otherParents.ElementAt(otherTotal - i);
600 0 : if (node != otherNode) {
601 0 : if (!parent) {
602 : // The two nodes are in different orphan subtrees.
603 0 : NS_ASSERTION(i == 0, "this shouldn't happen");
604 0 : return node < otherNode ? -1 : 1;
605 : }
606 :
607 0 : int32_t index = parent->IndexOf(node);
608 0 : int32_t otherIndex = parent->IndexOf(otherNode);
609 0 : NS_ASSERTION(index != otherIndex && index >= 0 && otherIndex >= 0,
610 : "invalid index in compareTreePosition");
611 :
612 0 : return index < otherIndex ? -1 : 1;
613 : }
614 :
615 0 : parent = node;
616 : }
617 :
618 : // One node is a descendant of the other. The one with the shortest
619 : // parent-chain is first in the document.
620 0 : return total < otherTotal ? -1 : 1;
621 : }
622 :
623 : /* static */
624 : txXPathNode*
625 0 : txXPathNativeNode::createXPathNode(nsIContent* aContent, bool aKeepRootAlive)
626 : {
627 0 : nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(aContent) : nullptr;
628 :
629 0 : return new txXPathNode(aContent, txXPathNode::eContent, root);
630 : }
631 :
632 : /* static */
633 : txXPathNode*
634 0 : txXPathNativeNode::createXPathNode(nsINode* aNode, bool aKeepRootAlive)
635 : {
636 0 : uint16_t nodeType = aNode->NodeType();
637 0 : if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) {
638 0 : nsCOMPtr<nsIAttribute> attr = do_QueryInterface(aNode);
639 0 : NS_ASSERTION(attr, "doesn't implement nsIAttribute");
640 :
641 0 : mozilla::dom::NodeInfo *nodeInfo = attr->NodeInfo();
642 : mozilla::dom::Element* parent =
643 0 : static_cast<Attr*>(attr.get())->GetElement();
644 0 : if (!parent) {
645 0 : return nullptr;
646 : }
647 :
648 0 : nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(parent) : nullptr;
649 :
650 0 : uint32_t i, total = parent->GetAttrCount();
651 0 : for (i = 0; i < total; ++i) {
652 0 : const nsAttrName* name = parent->GetAttrNameAt(i);
653 0 : if (nodeInfo->Equals(name->LocalName(), name->NamespaceID())) {
654 0 : return new txXPathNode(parent, i, root);
655 : }
656 : }
657 :
658 0 : NS_ERROR("Couldn't find the attribute in its parent!");
659 :
660 0 : return nullptr;
661 : }
662 :
663 : uint32_t index;
664 0 : nsINode* root = aKeepRootAlive ? aNode : nullptr;
665 :
666 0 : if (nodeType == nsIDOMNode::DOCUMENT_NODE) {
667 0 : index = txXPathNode::eDocument;
668 : }
669 : else {
670 0 : index = txXPathNode::eContent;
671 0 : if (root) {
672 0 : root = txXPathNode::RootOf(root);
673 : }
674 : }
675 :
676 0 : return new txXPathNode(aNode, index, root);
677 : }
678 :
679 : /* static */
680 : txXPathNode*
681 0 : txXPathNativeNode::createXPathNode(nsIDOMDocument* aDocument)
682 : {
683 0 : nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
684 0 : return new txXPathNode(document);
685 : }
686 :
687 : /* static */
688 : nsINode*
689 0 : txXPathNativeNode::getNode(const txXPathNode& aNode)
690 : {
691 0 : if (!aNode.isAttribute()) {
692 0 : return aNode.mNode;
693 : }
694 :
695 0 : const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
696 :
697 0 : nsAutoString namespaceURI;
698 0 : nsContentUtils::NameSpaceManager()->GetNameSpaceURI(name->NamespaceID(), namespaceURI);
699 :
700 0 : nsCOMPtr<Element> element = do_QueryInterface(aNode.mNode);
701 0 : nsDOMAttributeMap* map = element->Attributes();
702 : return map->GetNamedItemNS(namespaceURI,
703 0 : nsDependentAtomString(name->LocalName()));
704 : }
705 :
706 : /* static */
707 : nsIContent*
708 0 : txXPathNativeNode::getContent(const txXPathNode& aNode)
709 : {
710 0 : NS_ASSERTION(aNode.isContent(),
711 : "Only call getContent on nsIContent wrappers!");
712 0 : return aNode.Content();
713 : }
714 :
715 : /* static */
716 : nsIDocument*
717 0 : txXPathNativeNode::getDocument(const txXPathNode& aNode)
718 : {
719 0 : NS_ASSERTION(aNode.isDocument(),
720 : "Only call getDocument on nsIDocument wrappers!");
721 0 : return aNode.Document();
722 : }
|