зеркало из https://github.com/mozilla/pjs.git
Bug 194387: Support parameter-passing in PI XSLT transformations. r/sr=peterv
This commit is contained in:
Родитель
198b2c0d8a
Коммит
2cc84a5fd3
|
@ -619,6 +619,7 @@ GK_ATOM(pre, "pre")
|
|||
GK_ATOM(preceding, "preceding")
|
||||
GK_ATOM(precedingSibling, "preceding-sibling")
|
||||
GK_ATOM(predicate, "predicate")
|
||||
GK_ATOM(prefix, "prefix")
|
||||
GK_ATOM(preserve, "preserve")
|
||||
GK_ATOM(preserveSpace, "preserve-space")
|
||||
GK_ATOM(preventdefault, "preventdefault")
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
#include "nsIContentPolicy.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsContentErrors.h"
|
||||
#include "nsIDOMProcessingInstruction.h"
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
#include "nsSVGAtoms.h"
|
||||
|
@ -230,6 +231,48 @@ nsXMLContentSink::MaybePrettyPrint()
|
|||
return printer->PrettyPrint(mDocument);
|
||||
}
|
||||
|
||||
static void
|
||||
CheckXSLTParamPI(nsIDOMProcessingInstruction* aPi,
|
||||
nsIDocumentTransformer* aProcessor,
|
||||
nsIDocument* aDocument)
|
||||
{
|
||||
nsAutoString target, data;
|
||||
aPi->GetTarget(target);
|
||||
|
||||
// Check for namespace declarations
|
||||
if (target.EqualsLiteral("xslt-param-namespace")) {
|
||||
aPi->GetData(data);
|
||||
nsAutoString prefix, namespaceAttr;
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::prefix,
|
||||
prefix);
|
||||
if (!prefix.IsEmpty() &&
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::_namespace,
|
||||
namespaceAttr)) {
|
||||
aProcessor->AddXSLTParamNamespace(prefix, namespaceAttr);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for actual parameters
|
||||
else if (target.EqualsLiteral("xslt-param")) {
|
||||
aPi->GetData(data);
|
||||
nsAutoString name, namespaceAttr, select, value;
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::name,
|
||||
name);
|
||||
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::_namespace,
|
||||
namespaceAttr);
|
||||
if (!nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::select, select)) {
|
||||
select.SetIsVoid(PR_TRUE);
|
||||
}
|
||||
if (!nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::value, value)) {
|
||||
value.SetIsVoid(PR_TRUE);
|
||||
}
|
||||
if (!name.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMNode> doc = do_QueryInterface(aDocument);
|
||||
aProcessor->AddXSLTParam(name, namespaceAttr, select, value, doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLContentSink::DidBuildModel()
|
||||
{
|
||||
|
@ -239,6 +282,21 @@ nsXMLContentSink::DidBuildModel()
|
|||
}
|
||||
|
||||
if (mXSLTProcessor) {
|
||||
|
||||
// Check for xslt-param and xslt-param-namespace PIs
|
||||
PRUint32 i;
|
||||
nsIContent* child;
|
||||
for (i = 0; (child = mDocument->GetChildAt(i)); ++i) {
|
||||
if (child->IsContentOfType(nsIContent::ePROCESSING_INSTRUCTION)) {
|
||||
nsCOMPtr<nsIDOMProcessingInstruction> pi = do_QueryInterface(child);
|
||||
CheckXSLTParamPI(pi, mXSLTProcessor, mDocument);
|
||||
}
|
||||
else if (child->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
// Only honor PIs in the prolog
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> currentDOMDoc(do_QueryInterface(mDocument));
|
||||
mXSLTProcessor->SetSourceContentModel(currentDOMDoc);
|
||||
// Since the processor now holds a reference to us we drop our reference
|
||||
|
|
|
@ -80,6 +80,14 @@ public:
|
|||
nsIPrincipal* aCallerPrincipal) = 0;
|
||||
NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource) = 0;
|
||||
NS_IMETHOD CancelLoads() = 0;
|
||||
|
||||
NS_IMETHOD AddXSLTParamNamespace(const nsString& aPrefix,
|
||||
const nsString& aNamespace) = 0;
|
||||
NS_IMETHOD AddXSLTParam(const nsString& aName,
|
||||
const nsString& aNamespace,
|
||||
const nsString& aValue,
|
||||
const nsString& aSelect,
|
||||
nsIDOMNode* aContextNode) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentTransformer,
|
||||
|
|
|
@ -51,12 +51,24 @@ txNamespaceMap::txNamespaceMap(const txNamespaceMap& aOther)
|
|||
}
|
||||
|
||||
nsresult
|
||||
txNamespaceMap::addNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI)
|
||||
txNamespaceMap::mapNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI)
|
||||
{
|
||||
nsIAtom* prefix = aPrefix == txXMLAtoms::_empty ? 0 : aPrefix;
|
||||
nsIAtom* prefix = aPrefix == txXMLAtoms::_empty ? nsnull : aPrefix;
|
||||
|
||||
PRInt32 nsId;
|
||||
if (!prefix && aNamespaceURI.IsEmpty()) {
|
||||
if (prefix && aNamespaceURI.IsEmpty()) {
|
||||
// Remove the mapping
|
||||
PRInt32 index = mPrefixes.IndexOf(prefix);
|
||||
if (index >= 0) {
|
||||
mPrefixes.RemoveObjectAt(index);
|
||||
mNamespaces.RemoveElementAt(index);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aNamespaceURI.IsEmpty()) {
|
||||
// Set default to empty namespace
|
||||
nsId = kNameSpaceID_None;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
return mRefCnt;
|
||||
}
|
||||
|
||||
nsresult addNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI);
|
||||
nsresult mapNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI);
|
||||
PRInt32 lookupNamespace(nsIAtom* aPrefix);
|
||||
PRInt32 lookupNamespace(const nsAString& aPrefix);
|
||||
PRInt32 lookupNamespaceWithDefault(const nsAString& aPrefix);
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "jsapi.h"
|
||||
#include "txExprParser.h"
|
||||
|
||||
static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
|
||||
|
||||
|
@ -242,13 +243,17 @@ txToFragmentHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
|
|||
class txVariable : public txIGlobalParameter
|
||||
{
|
||||
public:
|
||||
txVariable(nsIVariant *aValue) : mValue(aValue),
|
||||
mTxValue(nsnull)
|
||||
txVariable(nsIVariant *aValue) : mValue(aValue)
|
||||
{
|
||||
NS_ASSERTION(aValue, "missing value");
|
||||
}
|
||||
txVariable(txAExprResult* aValue) : mTxValue(aValue)
|
||||
{
|
||||
NS_ASSERTION(aValue, "missing value");
|
||||
}
|
||||
nsresult getValue(txAExprResult** aValue)
|
||||
{
|
||||
NS_ASSERTION(mValue, "variablevalue is null");
|
||||
NS_ASSERTION(mValue || mTxValue, "variablevalue is null");
|
||||
|
||||
if (!mTxValue) {
|
||||
nsresult rv = Convert(mValue, getter_AddRefs(mTxValue));
|
||||
|
@ -272,6 +277,12 @@ public:
|
|||
mValue = aValue;
|
||||
mTxValue = nsnull;
|
||||
}
|
||||
void setValue(txAExprResult* aValue)
|
||||
{
|
||||
NS_ASSERTION(aValue, "setting variablevalue to null");
|
||||
mValue = nsnull;
|
||||
mTxValue = aValue;
|
||||
}
|
||||
|
||||
private:
|
||||
static nsresult Convert(nsIVariant *aValue, txAExprResult** aResult);
|
||||
|
@ -364,6 +375,155 @@ txMozillaXSLTProcessor::SetSourceContentModel(nsIDOMNode* aSourceDOM)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
txMozillaXSLTProcessor::AddXSLTParamNamespace(const nsString& aPrefix,
|
||||
const nsString& aNamespace)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> pre = do_GetAtom(aPrefix);
|
||||
return mParamNamespaceMap.mapNamespace(pre, aNamespace);
|
||||
}
|
||||
|
||||
|
||||
class txXSLTParamContext : public txIParseContext,
|
||||
public txIEvalContext
|
||||
{
|
||||
public:
|
||||
txXSLTParamContext(txNamespaceMap *aResolver, txXPathNode& aContext,
|
||||
txResultRecycler* aRecycler)
|
||||
: mResolver(aResolver),
|
||||
mContext(aContext),
|
||||
mRecycler(aRecycler)
|
||||
{
|
||||
}
|
||||
|
||||
// txIParseContext
|
||||
nsresult resolveNamespacePrefix(nsIAtom* aPrefix, PRInt32& aID)
|
||||
{
|
||||
aID = mResolver->lookupNamespace(aPrefix);
|
||||
return aID == kNameSpaceID_Unknown ? NS_ERROR_DOM_NAMESPACE_ERR :
|
||||
NS_OK;
|
||||
}
|
||||
nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID,
|
||||
FunctionCall*& aFunction)
|
||||
{
|
||||
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
|
||||
}
|
||||
PRBool caseInsensitiveNameTests()
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
void SetErrorOffset(PRUint32 aOffset)
|
||||
{
|
||||
}
|
||||
|
||||
// txIEvalContext
|
||||
nsresult getVariable(PRInt32 aNamespace, nsIAtom* aLName,
|
||||
txAExprResult*& aResult)
|
||||
{
|
||||
aResult = nsnull;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
PRBool isStripSpaceAllowed(const txXPathNode& aNode)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
void* getPrivateContext()
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
txResultRecycler* recycler()
|
||||
{
|
||||
return mRecycler;
|
||||
}
|
||||
void receiveError(const nsAString& aMsg, nsresult aRes)
|
||||
{
|
||||
}
|
||||
const txXPathNode& getContextNode()
|
||||
{
|
||||
return mContext;
|
||||
}
|
||||
PRUint32 size()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
PRUint32 position()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
txNamespaceMap *mResolver;
|
||||
txXPathNode& mContext;
|
||||
txResultRecycler* mRecycler;
|
||||
|
||||
};
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
txMozillaXSLTProcessor::AddXSLTParam(const nsString& aName,
|
||||
const nsString& aNamespace,
|
||||
const nsString& aSelect,
|
||||
const nsString& aValue,
|
||||
nsIDOMNode* aContext)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (aSelect.IsVoid() == aValue.IsVoid()) {
|
||||
// Ignore if neither or both are specified
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<txAExprResult> value;
|
||||
if (!aSelect.IsVoid()) {
|
||||
|
||||
// Set up context
|
||||
nsAutoPtr<txXPathNode> contextNode =
|
||||
txXPathNativeNode::createXPathNode(aContext);
|
||||
NS_ENSURE_TRUE(contextNode, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (!mRecycler) {
|
||||
mRecycler = new txResultRecycler;
|
||||
NS_ENSURE_TRUE(mRecycler, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
txXSLTParamContext paramContext(&mParamNamespaceMap, *contextNode,
|
||||
mRecycler);
|
||||
|
||||
// Parse
|
||||
nsAutoPtr<Expr> expr;
|
||||
rv = txExprParser::createExpr(aSelect, ¶mContext,
|
||||
getter_Transfers(expr));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Evaluate
|
||||
rv = expr->evaluate(¶mContext, getter_AddRefs(value));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
value = new StringResult(aValue, nsnull);
|
||||
NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> name = do_GetAtom(aName);
|
||||
PRInt32 nsId = kNameSpaceID_Unknown;
|
||||
rv = nsContentUtils::NameSpaceManager()->
|
||||
RegisterNameSpace(aNamespace, nsId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
txExpandedName varName(nsId, name);
|
||||
txVariable* var = (txVariable*)mVariables.get(varName);
|
||||
if (var) {
|
||||
var->setValue(value);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
var = new txVariable(value);
|
||||
NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return mVariables.add(varName, var);
|
||||
}
|
||||
|
||||
class nsTransformBlockerEvent : public nsRunnable {
|
||||
public:
|
||||
nsRefPtr<txMozillaXSLTProcessor> mProcessor;
|
||||
|
@ -755,7 +915,7 @@ txMozillaXSLTProcessor::SetParameter(const nsAString & aNamespaceURI,
|
|||
nsCOMPtr<nsIAtom> localName = do_GetAtom(aLocalName);
|
||||
txExpandedName varName(nsId, localName);
|
||||
|
||||
txVariable* var = (txVariable*)mVariables.get(varName);
|
||||
txVariable* var = NS_STATIC_CAST(txVariable*, mVariables.get(varName));
|
||||
if (var) {
|
||||
var->setValue(value);
|
||||
return NS_OK;
|
||||
|
|
|
@ -45,12 +45,14 @@
|
|||
#include "nsIXSLTProcessor.h"
|
||||
#include "nsIXSLTProcessorObsolete.h"
|
||||
#include "txExpandedNameMap.h"
|
||||
#include "txNamespaceMap.h"
|
||||
|
||||
class nsIDOMNode;
|
||||
class nsIPrincipal;
|
||||
class nsIURI;
|
||||
class nsIXMLContentSink;
|
||||
class txStylesheet;
|
||||
class txResultRecycler;
|
||||
|
||||
/* bacd8ad0-552f-11d3-a9f7-000064657374 */
|
||||
#define TRANSFORMIIX_XSLT_PROCESSOR_CID \
|
||||
|
@ -95,6 +97,13 @@ public:
|
|||
nsIPrincipal* aCallerPrincipal);
|
||||
NS_IMETHOD SetSourceContentModel(nsIDOMNode* aSource);
|
||||
NS_IMETHOD CancelLoads() {return NS_OK;};
|
||||
NS_IMETHOD AddXSLTParamNamespace(const nsString& aPrefix,
|
||||
const nsString& aNamespace);
|
||||
NS_IMETHOD AddXSLTParam(const nsString& aName,
|
||||
const nsString& aNamespace,
|
||||
const nsString& aSelect,
|
||||
const nsString& aValue,
|
||||
nsIDOMNode* aContext);
|
||||
|
||||
// nsIDocumentObserver interface
|
||||
NS_DECL_NSIDOCUMENTOBSERVER
|
||||
|
@ -126,6 +135,8 @@ private:
|
|||
nsString mErrorText, mSourceText;
|
||||
nsCOMPtr<nsITransformObserver> mObserver;
|
||||
txExpandedNameMap mVariables;
|
||||
txNamespaceMap mParamNamespaceMap;
|
||||
nsRefPtr<txResultRecycler> mRecycler;
|
||||
};
|
||||
|
||||
extern nsresult TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
|
||||
|
|
|
@ -129,11 +129,11 @@ txStylesheetCompiler::startElement(PRInt32 aNamespaceID, nsIAtom* aLocalName,
|
|||
}
|
||||
|
||||
if (attr->mLocalName == txXMLAtoms::xmlns) {
|
||||
mElementContext->mMappings->addNamespace(nsnull, attr->mValue);
|
||||
mElementContext->mMappings->mapNamespace(nsnull, attr->mValue);
|
||||
}
|
||||
else {
|
||||
mElementContext->mMappings->
|
||||
addNamespace(attr->mLocalName, attr->mValue);
|
||||
mapNamespace(attr->mLocalName, attr->mValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ txStylesheetCompiler::startElement(const PRUnichar *aName,
|
|||
}
|
||||
|
||||
rv = mElementContext->mMappings->
|
||||
addNamespace(prefixToBind, atts[i].mValue);
|
||||
mapNamespace(prefixToBind, atts[i].mValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче