1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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/. */
8 * A representation of the XSLT additional function: document()
11 #include "nsGkAtoms.h"
12 #include "txIXPathContext.h"
13 #include "txXSLTFunctions.h"
14 #include "txExecutionState.h"
15 #include "txURIUtils.h"
18 * Creates a new DocumentFunctionCall.
20 DocumentFunctionCall::DocumentFunctionCall(const nsAString
& aBaseURI
)
21 : mBaseURI(aBaseURI
) {}
23 static void retrieveNode(txExecutionState
* aExecutionState
,
24 const nsAString
& aUri
, const nsAString
& aBaseUri
,
25 txNodeSet
* aNodeSet
) {
27 URIUtils::resolveHref(aUri
, aBaseUri
, absUrl
);
29 int32_t hash
= absUrl
.RFindChar(char16_t('#'));
30 uint32_t urlEnd
, fragStart
, fragEnd
;
31 if (hash
== kNotFound
) {
32 urlEnd
= absUrl
.Length();
38 fragEnd
= absUrl
.Length();
41 nsDependentSubstring
docUrl(absUrl
, 0, urlEnd
);
42 nsDependentSubstring
frag(absUrl
, fragStart
, fragEnd
);
44 const txXPathNode
* loadNode
= aExecutionState
->retrieveDocument(docUrl
);
47 aNodeSet
->add(*loadNode
);
49 txXPathTreeWalker
walker(*loadNode
);
50 if (walker
.moveToElementById(frag
)) {
51 aNodeSet
->add(walker
.getCurrentPosition());
58 * Evaluates this Expr based on the given context node and processor state
59 * NOTE: the implementation is incomplete since it does not make use of the
60 * second argument (base URI)
61 * @param context the context node for evaluation of this Expr
62 * @return the result of the evaluation
64 nsresult
DocumentFunctionCall::evaluate(txIEvalContext
* aContext
,
65 txAExprResult
** aResult
) {
67 txExecutionState
* es
=
68 static_cast<txExecutionState
*>(aContext
->getPrivateContext());
70 RefPtr
<txNodeSet
> nodeSet
;
71 nsresult rv
= aContext
->recycler()->getNodeSet(getter_AddRefs(nodeSet
));
72 NS_ENSURE_SUCCESS(rv
, rv
);
74 // document(object, node-set?)
75 if (!requireParams(1, 2, aContext
)) {
76 return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT
;
79 RefPtr
<txAExprResult
> exprResult1
;
80 rv
= mParams
[0]->evaluate(aContext
, getter_AddRefs(exprResult1
));
81 NS_ENSURE_SUCCESS(rv
, rv
);
84 bool baseURISet
= false;
86 if (mParams
.Length() == 2) {
87 // We have 2 arguments, get baseURI from the first node
88 // in the resulting nodeset
89 RefPtr
<txNodeSet
> nodeSet2
;
90 rv
= evaluateToNodeSet(mParams
[1], aContext
, getter_AddRefs(nodeSet2
));
91 NS_ENSURE_SUCCESS(rv
, rv
);
93 // Make this true, even if nodeSet2 is empty. For relative URLs,
94 // we'll fail to load the document with an empty base URI, and for
95 // absolute URLs, the base URI doesn't matter
98 if (!nodeSet2
->isEmpty()) {
99 rv
= txXPathNodeUtils::getBaseURI(nodeSet2
->get(0), baseURI
);
100 NS_ENSURE_SUCCESS(rv
, rv
);
104 if (exprResult1
->getResultType() == txAExprResult::NODESET
) {
105 // The first argument is a NodeSet, iterate on its nodes
106 txNodeSet
* nodeSet1
=
107 static_cast<txNodeSet
*>(static_cast<txAExprResult
*>(exprResult1
));
109 for (i
= 0; i
< nodeSet1
->size(); ++i
) {
110 const txXPathNode
& node
= nodeSet1
->get(i
);
112 txXPathNodeUtils::appendNodeValue(node
, uriStr
);
114 // if the second argument wasn't specified, use
115 // the baseUri of node itself
116 rv
= txXPathNodeUtils::getBaseURI(node
, baseURI
);
117 NS_ENSURE_SUCCESS(rv
, rv
);
119 retrieveNode(es
, uriStr
, baseURI
, nodeSet
);
122 NS_ADDREF(*aResult
= nodeSet
);
127 // The first argument is not a NodeSet
129 exprResult1
->stringValue(uriStr
);
130 const nsAString
* base
= baseURISet
? &baseURI
: &mBaseURI
;
131 retrieveNode(es
, uriStr
, *base
, nodeSet
);
133 NS_ADDREF(*aResult
= nodeSet
);
138 Expr::ResultType
DocumentFunctionCall::getReturnType() {
139 return NODESET_RESULT
;
142 bool DocumentFunctionCall::isSensitiveTo(ContextSensitivity aContext
) {
143 return (aContext
& PRIVATE_CONTEXT
) || argsSensitiveTo(aContext
);
147 void DocumentFunctionCall::appendName(nsAString
& aDest
) {
148 aDest
.Append(nsGkAtoms::document
->GetUTF16String());