Bug 95779 - Key cached expressions and patterns on node they appear in rather then string.

r=Pike sr=jst
This commit is contained in:
sicking%bigfoot.com 2001-11-09 23:46:36 +00:00
parent 9dbad9b635
commit 79768f9dfc
16 changed files with 326 additions and 286 deletions

View File

@ -186,6 +186,21 @@ MBool Element::getAttr(txAtom* aLocalName, PRInt32 aNSID,
return MB_FALSE;
}
/*
* Call nsIContent::GetAttr for the localname and nsID.
*/
MBool Element::hasAttr(txAtom* aLocalName, PRInt32 aNSID)
{
nsCOMPtr<nsIContent> cont(do_QueryInterface(nsObject));
NS_ASSERTION(cont, "Element doesn't implement nsIContent");
if (!cont)
return MB_FALSE;
nsresult rv;
nsAutoString tmp;
rv = cont->GetAttr(aNSID, aLocalName, tmp);
NS_ENSURE_SUCCESS(rv, MB_FALSE);
return rv != NS_CONTENT_ATTR_NOT_THERE;
}
/*
* Call nsIDOMElement::SetAttributeNode passing it the nsIDOMAttr object wrapped

View File

@ -433,6 +433,7 @@ class Element : public Node
// txXPathNode functions
MBool getLocalName(txAtom** aLocalName);
MBool getAttr(txAtom* aLocalName, PRInt32 aNSID, String& aValue);
MBool hasAttr(txAtom* aLocalName, PRInt32 aNSID);
};
/*

View File

@ -223,6 +223,28 @@ MBool Element::getAttr(txAtom* aLocalName, PRInt32 aNSID,
TX_IF_RELEASE_ATOM(localName);
return MB_TRUE;
}
TX_RELEASE_IF_ATOM(localName);
item = item->next;
}
return MB_FALSE;
}
//
// Return true if the attribute specified by localname and nsID
// exists. Return false otherwise.
//
MBool Element::hasAttr(txAtom* aLocalName, PRInt32 aNSID)
{
AttrMap::ListItem* item = mAttributes.firstItem;
while (item) {
Attr* attrNode = (Attr*)item->node;
txAtom* localName;
if (attrNode->getLocalName(&localName) &&
aNSID == attrNode->getNamespaceID() &&
aLocalName == localName) {
TX_IF_RELEASE_ATOM(localName);
return MB_TRUE;
}
TX_IF_RELEASE_ATOM(localName);
item = item->next;
}

View File

@ -437,6 +437,7 @@ class Element : public NodeDefinition
MBool getLocalName(txAtom** aLocalName);
PRInt32 getNamespaceID();
MBool getAttr(txAtom* aLocalName, PRInt32 aNSID, String& aValue);
MBool hasAttr(txAtom* aLocalName, PRInt32 aNSID);
private:
AttrMap mAttributes;

View File

@ -154,15 +154,16 @@ AttributeValueTemplate* ExprParser::createAttributeValueTemplate
} //-- createAttributeValueTemplate
Expr* ExprParser::createExpr(const String& pattern) {
ExprLexer lexer(pattern);
Expr* ExprParser::createExpr(const String& aExpression)
{
ExprLexer lexer(aExpression);
return createExpr(lexer);
} //-- createExpr
Expr* ExprParser::createPatternExpr(const String& pattern) {
ExprLexer lexer(pattern);
Expr* expr = createUnionExpr(lexer);
return expr;
Pattern* ExprParser::createPattern(const String& aPattern)
{
ExprLexer lexer(aPattern);
return createUnionExpr(lexer);
} //-- createPatternExpr
//--------------------/

View File

@ -51,8 +51,8 @@ public:
**/
~ExprParser();
Expr* createExpr (const String& pattern);
Expr* createPatternExpr (const String& pattern);
Expr* createExpr(const String& aExpression);
Pattern* createPattern(const String& aPattern);
/**
* Creates an Attribute Value Template using the given value

View File

@ -31,11 +31,11 @@
#include "Numbering.h"
#include "Names.h"
void Numbering::doNumbering
(Element* xslNumber, String& dest, Node* context, ProcessorState* ps)
void Numbering::doNumbering(Element* xslNumber, String& dest, Node* context,
ProcessorState* ps)
{
if ( !xslNumber ) return;
if (!xslNumber)
return;
int* counts = 0;
int nbrOfCounts = 0;
@ -43,7 +43,9 @@ void Numbering::doNumbering
String valueAttr = xslNumber->getAttribute(VALUE_ATTR);
//-- check for expr
if (!valueAttr.isEmpty()) {
Expr* expr = ps->getExpr(valueAttr);
Expr* expr = ps->getExpr(xslNumber, ProcessorState::ValueAttr);
if (!expr)
return;
nbrOfCounts = 1;
counts = new int[1];
ExprResult* result = expr->evaluate(context, ps);
@ -57,11 +59,16 @@ void Numbering::doNumbering
String countAttr = xslNumber->getAttribute(COUNT_ATTR);
PatternExpr* countExpr = 0;
Pattern* countPattern;
MBool ownsPattern;
if (!countAttr.isEmpty()) {
countExpr = ps->getPatternExpr(countAttr);
countPattern = ps->getPattern(xslNumber,
ProcessorState::CountAttr);
ownsPattern = MB_FALSE;
}
else {
// Actually, this code should probobly use NodeTests instead
switch(context->getNodeType()) {
case Node::ATTRIBUTE_NODE:
countAttr.append('@');
@ -84,8 +91,15 @@ void Numbering::doNumbering
countAttr.append("node()[false()]"); //-- for now
break;
}
countExpr = ps->getPatternExpr(countAttr);
ExprParser parser;
countPattern = parser.createPattern(countAttr);
ownsPattern = MB_TRUE;
}
if (!countPattern) {
delete counts;
return;
}
NodeSet* nodes = 0;
int cnum = 0;
@ -94,20 +108,30 @@ void Numbering::doNumbering
PatternExpr* from = 0;
if (MULTIPLE_VALUE.isEqual(level))
nodes = getAncestorsOrSelf(countExpr, from, context, ps, MB_FALSE);
nodes = getAncestorsOrSelf(countPattern,
from,
context,
ps,
MB_FALSE);
//else if (ANY_VALUE.isEqual(level))
// nodes = getAnyPreviousNodes(countExpr, context, ps);
else
nodes = getAncestorsOrSelf(countExpr, from, context, ps, MB_TRUE);
nodes = getAncestorsOrSelf(countPattern,
from,
context,
ps,
MB_TRUE);
nbrOfCounts = nodes->size();
counts = new int[nbrOfCounts];
cnum = 0;
for (int i = nodes->size()-1; i >= 0; i--) {
counts[cnum++] =
countPreceedingSiblings(countExpr, nodes->get(i), ps);
countPreceedingSiblings(countPattern, nodes->get(i), ps);
}
delete nodes;
if (ownsPattern)
delete countPattern;
}
//-- format counts
for ( int i = 0; i < nbrOfCounts; i++) {

View File

@ -61,11 +61,12 @@ const String ProcessorState::wrapperNS = "http://www.mitre.org/TransforMi
/**
* Creates a new ProcessorState
**/
ProcessorState::ProcessorState() {
this->mSourceDocument = NULL;
this->xslDocument = NULL;
this->resultDocument = NULL;
currentAction = 0;
ProcessorState::ProcessorState()
{
mSourceDocument = 0;
xslDocument = 0;
resultDocument = 0;
mXPathParseContext = 0;
initialize();
} //-- ProcessorState
@ -73,11 +74,14 @@ ProcessorState::ProcessorState() {
* Creates a new ProcessorState for the given XSL document
* and resultDocument
**/
ProcessorState::ProcessorState(Document& sourceDocument, Document& xslDocument, Document& resultDocument) {
this->mSourceDocument = &sourceDocument;
this->xslDocument = &xslDocument;
this->resultDocument = &resultDocument;
currentAction = 0;
ProcessorState::ProcessorState(Document* aSourceDocument,
Document* aXslDocument,
Document* aResultDocument)
{
mSourceDocument = aSourceDocument;
xslDocument = aXslDocument;
resultDocument = aResultDocument;
mXPathParseContext = 0;
initialize();
} //-- ProcessorState
@ -92,15 +96,6 @@ ProcessorState::~ProcessorState() {
delete (NamedMap*) variableSets.pop();
}
//-- clean up XSLT actions stack
while (currentAction) {
XSLTAction* item = currentAction;
item->node = 0;
currentAction = item->prev;
item->prev = 0;
delete item;
}
// Delete all ImportFrames
txListIterator iter(&mImportFrames);
while (iter.hasNext())
@ -211,7 +206,10 @@ void ProcessorState::addTemplate(Element* aXslTemplate,
return;
}
templ->mTemplate = aXslTemplate;
templ->mMatch = exprParser.createPatternExpr(match);
Element* oldContext = mXPathParseContext;
mXPathParseContext = aXslTemplate;
templ->mMatch = exprParser.createPattern(match);
mXPathParseContext = oldContext;
if (templ->mMatch)
templates->add(templ);
else
@ -251,7 +249,7 @@ void ProcessorState::addLREStylesheet(Document* aStylesheet,
templ->mTemplate = aStylesheet;
String match("/");
templ->mMatch = exprParser.createPatternExpr(match);
templ->mMatch = exprParser.createPattern(match);
if (templ->mMatch)
templates->add(templ);
else
@ -389,16 +387,7 @@ Node* ProcessorState::retrieveDocument(const String& uri, const String& baseUri)
String errMsg;
XMLParser xmlParser;
NS_ASSERTION(currentAction && currentAction->node,
"missing currentAction->node");
Document* loaderDoc;
if (currentAction->node->getNodeType() == Node::DOCUMENT_NODE)
loaderDoc = (Document*)currentAction->node;
else
loaderDoc = currentAction->node->getOwnerDocument();
xmlDoc = xmlParser.getDocumentFromURI(docUrl, loaderDoc, errMsg);
xmlDoc = xmlParser.getDocumentFromURI(docUrl, xslDocument, errMsg);
if (!xmlDoc) {
String err("Couldn't load document '");
@ -529,22 +518,82 @@ Stack* ProcessorState::getDefaultNSURIStack() {
return &defaultNameSpaceURIStack;
} //-- getDefaultNSURIStack
Expr* ProcessorState::getExpr(const String& pattern) {
// NS_IMPL_LOG(XPATH)
// PRINTF("Resolving XPath Expr %s",pattern.toCharArray());
// FLUSH();
Expr* expr = (Expr*)exprHash.get(pattern);
if ( !expr ) {
expr = exprParser.createExpr(pattern);
if ( !expr ) {
String err = "Error in parsing XPath expression: ";
err.append(pattern);
expr = new ErrorFunctionCall(err);
Expr* ProcessorState::getExpr(Element* aElem, ExprAttr aAttr)
{
NS_ASSERTION(aElem, "missing element while getting expression");
// This is how we'll have to do it for now
mXPathParseContext = aElem;
Expr* expr = (Expr*)mExprHashes[aAttr].get(aElem);
if (!expr) {
String attr;
switch (aAttr) {
case SelectAttr:
attr = aElem->getAttribute(SELECT_ATTR);
break;
case TestAttr:
attr = aElem->getAttribute(TEST_ATTR);
break;
case ValueAttr:
attr = aElem->getAttribute(VALUE_ATTR);
break;
}
// This is how we should do it once we namespaceresolve during parsing
//Element* oldContext = mXPathParseContext;
//mXPathParseContext = aElem;
expr = exprParser.createExpr(attr);
//mXPathParseContext = oldContext;
if (!expr) {
String err = "Error in parsing XPath expression: ";
err.append(attr);
recieveError(err);
}
else {
mExprHashes[aAttr].put(aElem, expr);
}
exprHash.put(pattern, expr);
}
return expr;
} //-- getExpr
}
PatternExpr* ProcessorState::getPattern(Element* aElem, PatternAttr aAttr)
{
NS_ASSERTION(aElem, "missing element while getting pattern");
// This is how we'll have to do it for now
mXPathParseContext = aElem;
Pattern* pattern = (Pattern*)mExprHashes[aAttr].get(aElem);
if (!pattern) {
String attr;
switch (aAttr) {
case CountAttr:
attr = aElem->getAttribute(COUNT_ATTR);
break;
case FromAttr:
attr = aElem->getAttribute(FROM_ATTR);
break;
}
// This is how we should do it once we namespaceresolve during parsing
//Element* oldContext = mXPathParseContext;
//mXPathParseContext = aElem;
pattern = exprParser.createPattern(attr);
//mXPathParseContext = oldContext;
if (!pattern) {
String err = "Error in parsing pattern: ";
err.append(attr);
recieveError(err);
}
else {
mPatternHashes[aAttr].put(aElem, pattern);
}
}
return pattern;
}
/*
* Returns the template associated with the given name, or
@ -580,18 +629,8 @@ void ProcessorState::getNameSpaceURI(const String& name, String& nameSpaceURI) {
* (ie. the stylesheet)
**/
void ProcessorState::getNameSpaceURIFromPrefix(const String& prefix, String& nameSpaceURI) {
XSLTAction* action = currentAction;
while (action) {
Node* node = action->node;
if (( node ) && (node->getNodeType() == Node::ELEMENT_NODE)) {
if (XMLDOMUtils::getNameSpace(prefix, (Element*) node, nameSpaceURI))
break;
}
action = action->prev;
}
if (mXPathParseContext)
XMLDOMUtils::getNameSpace(prefix, mXPathParseContext, nameSpaceURI);
} //-- getNameSpaceURI
/**
@ -614,15 +653,6 @@ OutputFormat* ProcessorState::getOutputFormat() {
return &format;
} //-- getOutputFormat
PatternExpr* ProcessorState::getPatternExpr(const String& pattern) {
PatternExpr* pExpr = (PatternExpr*)patternExprHash.get(pattern);
if ( !pExpr ) {
pExpr = exprParser.createPatternExpr(pattern);
patternExprHash.put(pattern, pExpr);
}
return pExpr;
} //-- getPatternExpr
Document* ProcessorState::getResultDocument() {
return resultDocument;
} //-- getResultDocument
@ -666,33 +696,6 @@ MBool ProcessorState::isXSLStripSpaceAllowed(Node* node) {
} //--isXSLStripSpaceAllowed
/**
* Returns the current XSLT action from the top of the stack.
* @returns the XSLT action from the top of the stack
**/
Node* ProcessorState::peekAction() {
NS_ASSERTION(currentAction, "currentAction is NULL, this is very bad");
if (currentAction)
return currentAction->node;
return NULL;
}
/**
* Removes the current XSLT action from the top of the stack.
* @returns the XSLT action after removing from the top of the stack
**/
Node* ProcessorState::popAction() {
Node* xsltAction = 0;
if (currentAction) {
xsltAction = currentAction->node;
XSLTAction* item = currentAction;
currentAction = currentAction->prev;
item->node = 0;
delete item;
}
return xsltAction;
} //-- popAction
/**
* Removes and returns the current source node being processed, from the stack
* @return the current source node
@ -724,22 +727,6 @@ void ProcessorState::processAttrValueTemplate(const String& aAttValue,
delete exprResult;
}
/**
* Adds the given XSLT action to the top of the action stack
**/
void ProcessorState::pushAction(Node* xsltAction) {
if (currentAction) {
XSLTAction* newAction = new XSLTAction;
newAction->prev = currentAction;
currentAction = newAction;
}
else {
currentAction = new XSLTAction;
currentAction->prev = 0;
}
currentAction->node = xsltAction;
} //-- pushAction
/**
* Sets the source node currently being processed
* @param node the source node to set as the "current" node
@ -816,8 +803,8 @@ void ProcessorState::shouldStripSpace(String& aNames,
/**
* Adds the supplied xsl:key to the set of keys
**/
MBool ProcessorState::addKey(Element* keyElem) {
String keyName = keyElem->getAttribute(NAME_ATTR);
MBool ProcessorState::addKey(Element* aKeyElem) {
String keyName = aKeyElem->getAttribute(NAME_ATTR);
if(!XMLUtils::isValidQName(keyName))
return MB_FALSE;
txXSLKey* xslKey = (txXSLKey*)xslKeys.get(keyName);
@ -827,8 +814,18 @@ MBool ProcessorState::addKey(Element* keyElem) {
return MB_FALSE;
xslKeys.put(keyName, xslKey);
}
return xslKey->addKey(keyElem->getAttribute(MATCH_ATTR), keyElem->getAttribute(USE_ATTR));
Element* oldContext = mXPathParseContext;
mXPathParseContext = aKeyElem;
Pattern* match;
match = exprParser.createPattern(aKeyElem->getAttribute(MATCH_ATTR));
Expr* use = exprParser.createExpr(aKeyElem->getAttribute(USE_ATTR));
mXPathParseContext = oldContext;
if (!match || !use || !xslKey->addKey(match, use)) {
delete match;
delete use;
return MB_FALSE;
}
return MB_TRUE;
}
/**
@ -1061,7 +1058,7 @@ FunctionCall* ProcessorState::resolveFunctionCall(const String& name) {
String err;
if (DOCUMENT_FN.isEqual(name)) {
return new DocumentFunctionCall(this);
return new DocumentFunctionCall(this, mXPathParseContext);
}
else if (KEY_FN.isEqual(name)) {
return new txKeyFunctionCall(this);
@ -1189,8 +1186,11 @@ void ProcessorState::initialize() {
variableSets.push(globalVars);
/* turn object deletion on for some of the Maps (NamedMap) */
exprHash.setObjectDeletion(MB_TRUE);
patternExprHash.setObjectDeletion(MB_TRUE);
mExprHashes[SelectAttr].setOwnership(Map::eOwnsItems);
mExprHashes[TestAttr].setOwnership(Map::eOwnsItems);
mExprHashes[ValueAttr].setOwnership(Map::eOwnsItems);
mPatternHashes[CountAttr].setOwnership(Map::eOwnsItems);
mPatternHashes[FromAttr].setOwnership(Map::eOwnsItems);
nameSpaceMap.setObjectDeletion(MB_TRUE);
//-- create NodeStack
@ -1210,8 +1210,6 @@ void ProcessorState::initialize() {
}
if ( element ) {
pushAction(element);
//-- process namespace nodes
NamedNodeMap* atts = element->getAttributes();
if ( atts ) {

View File

@ -37,6 +37,7 @@
#include "Expr.h"
#include "StringList.h"
#include "OutputFormat.h"
#include "Map.h"
class txXSLKey;
class txDecimalFormat;
@ -61,7 +62,9 @@ public:
* Creates a new ProcessorState for the given XSL document
* And result Document
**/
ProcessorState(Document& sourceDocument, Document& xslDocument, Document& resultDocument);
ProcessorState(Document* aSourceDocument,
Document* aXslDocument,
Document* aResultDocument);
/**
* Destroys this ProcessorState
@ -180,8 +183,19 @@ public:
Stack* getVariableSetStack();
Expr* getExpr(const String& pattern);
PatternExpr* getPatternExpr(const String& pattern);
enum ExprAttr {
SelectAttr = 0,
TestAttr,
ValueAttr
};
enum PatternAttr {
CountAttr = 0,
FromAttr
};
Expr* getExpr(Element* aElem, ExprAttr aAttr);
Pattern* getPattern(Element* aElem, PatternAttr aAttr);
/**
* Returns a pointer to the result document
@ -237,23 +251,11 @@ public:
**/
MBool isXSLStripSpaceAllowed(Node* node);
/**
* Returns the current XSLT action from the top of the stack.
* @returns the XSLT action from the top of the stack
**/
Node* peekAction();
/**
* Adds the set of names to the Whitespace preserving element set
**/
void preserveSpace(String& names);
/**
* Removes the current XSLT action from the top of the stack.
* @returns the XSLT action after removing from the top of the stack
**/
Node* popAction();
/**
* Removes and returns the current node being processed from the stack
* @return the current node
@ -264,11 +266,6 @@ public:
Node* aContext,
String& aResult);
/**
* Adds the given XSLT action to the top of the action stack
**/
void pushAction(Node* xsltAction);
/**
* Sets the given source node as the "current node" being processed
* @param node the source node currently being processed
@ -299,7 +296,7 @@ public:
/**
* Adds the supplied xsl:key to the set of keys
**/
MBool addKey(Element* xslKey);
MBool addKey(Element* aKeyElem);
/**
* Returns the key with the supplied name
@ -389,11 +386,6 @@ private:
enum XMLSpaceMode {STRIP = 0, DEFAULT, PRESERVE};
struct XSLTAction {
Node* node;
XSLTAction* prev;
};
struct MatchableTemplate {
Node* mTemplate;
Pattern* mMatch;
@ -414,12 +406,7 @@ private:
/**
* List of import containers. Sorted by ascending import precedence
**/
List importFrames;
/**
* A map for named attribute sets
**/
List mImportFrames;
txList mImportFrames;
/**
* Current stack of nodes, where we are in the result document tree
@ -459,14 +446,23 @@ private:
*/
MBool defaultDecimalFormatSet;
/*
* List of hashes with parsed expression. Every listitem holds the
* expressions for an attribute name
*/
Map mExprHashes[3];
XSLTAction* currentAction;
/*
* List of hashes with parsed patterns. Every listitem holds the
* patterns for an attribute name
*/
Map mPatternHashes[2];
Element* mXPathParseContext;
Stack nodeSetStack;
Document* mSourceDocument;
Document* xslDocument;
Document* resultDocument;
NamedMap exprHash;
NamedMap patternExprHash;
Stack variableSets;
ExprParser exprParser;
String xsltNameSpace;

View File

@ -137,15 +137,18 @@ XSLTProcessor::XSLTProcessor() {
xslTypes.put(WHEN, new XSLType(XSLType::WHEN));
xslTypes.put(WITH_PARAM, new XSLType(XSLType::WITH_PARAM));
//-- proprietary debug elements
xslTypes.put("expr-debug", new XSLType(XSLType::EXPR_DEBUG));
// Create default expressions
ExprParser parser;
String node("node()");
mNodeExpr = parser.createExpr(node);
} //-- XSLTProcessor
/**
* Default destructor
**/
XSLTProcessor::~XSLTProcessor() {
//-- currently does nothing, but added for future use
delete mNodeExpr;
} //-- ~XSLTProcessor
#ifndef TX_EXE
@ -740,7 +743,7 @@ Document* XSLTProcessor::process
Document* result = new Document();
//-- create a new ProcessorState
ProcessorState ps(xmlDocument, xslDocument, *result);
ProcessorState ps(&xmlDocument, &xslDocument, result);
//-- add error observers
ListIterator* iter = errorObservers.iterator();
@ -786,7 +789,7 @@ void XSLTProcessor::process
Document* result = new Document();
//-- create a new ProcessorState
ProcessorState ps(xmlDocument, xslDocument, *result);
ProcessorState ps(&xmlDocument, &xslDocument, result);
//-- add error observers
ListIterator* iter = errorObservers.iterator();
@ -1077,11 +1080,9 @@ void XSLTProcessor::processAction
else if (nodeType == Node::ELEMENT_NODE) {
String nodeName = xslAction->getNodeName();
PatternExpr* pExpr = 0;
Expr* expr = 0;
Element* actionElement = (Element*)xslAction;
ps->pushAction(actionElement);
switch ( getElementType(nodeName, ps) ) {
@ -1090,15 +1091,18 @@ void XSLTProcessor::processAction
{
const String& mode =
actionElement->getAttribute(MODE_ATTR);
String selectAtt = actionElement->getAttribute(SELECT_ATTR);
if (selectAtt.isEmpty())
selectAtt = "node()";
expr = ps->getExpr(selectAtt);
if (!expr) {
// XXX ErrorReport: out of memory
if (actionElement->hasAttr(txXSLTAtoms::select,
kNameSpaceID_None))
expr = ps->getExpr(actionElement,
ProcessorState::SelectAttr);
else
expr = mNodeExpr;
if (!expr)
break;
}
ExprResult* exprResult = expr->evaluate(node, ps);
NodeSet* nodeSet = 0;
if ( exprResult->getResultType() == ExprResult::NODESET ) {
nodeSet = (NodeSet*)exprResult;
@ -1218,7 +1222,11 @@ void XSLTProcessor::processAction
ps)) {
case XSLType::WHEN :
{
expr = ps->getExpr(xslTemplate->getAttribute(TEST_ATTR));
expr = ps->getExpr(xslTemplate,
ProcessorState::TestAttr);
if (!expr)
break;
ExprResult* result = expr->evaluate(node, ps);
if (result && result->booleanValue()) {
processChildren(node, xslTemplate, ps);
@ -1264,8 +1272,10 @@ void XSLTProcessor::processAction
//-- xsl:copy-of
case XSLType::COPY_OF:
{
String selectAtt = actionElement->getAttribute(SELECT_ATTR);
Expr* expr = ps->getExpr(selectAtt);
expr = ps->getExpr(actionElement, ProcessorState::SelectAttr);
if (!expr)
break;
ExprResult* exprResult = expr->evaluate(node, ps);
xslCopyOf(exprResult, ps);
delete exprResult;
@ -1321,17 +1331,11 @@ void XSLTProcessor::processAction
//-- xsl:for-each
case XSLType::FOR_EACH :
{
String selectAtt = actionElement->getAttribute(SELECT_ATTR);
if (selectAtt.isEmpty())
{
notifyError("missing required select attribute for xsl:for-each");
expr = ps->getExpr(actionElement, ProcessorState::SelectAttr);
if (!expr)
break;
}
pExpr = ps->getPatternExpr(selectAtt);
ExprResult* exprResult = pExpr->evaluate(node, ps);
ExprResult* exprResult = expr->evaluate(node, ps);
NodeSet* nodeSet = 0;
if ( exprResult->getResultType() == ExprResult::NODESET ) {
nodeSet = (NodeSet*)exprResult;
@ -1386,10 +1390,9 @@ void XSLTProcessor::processAction
// xsl:if
case XSLType::IF :
{
String selectAtt = actionElement->getAttribute(TEST_ATTR);
expr = ps->getExpr(selectAtt);
//-- check for Error
/* add later when we create ErrResult */
expr = ps->getExpr(actionElement, ProcessorState::TestAttr);
if (!expr)
break;
ExprResult* exprResult = expr->evaluate(node, ps);
if ( exprResult->booleanValue() ) {
@ -1494,52 +1497,13 @@ void XSLTProcessor::processAction
ps->addToResultTree(text);
break;
}
case XSLType::EXPR_DEBUG: //-- proprietary debug element
{
String exprAtt = actionElement->getAttribute(EXPR_ATTR);
Expr* expr = ps->getExpr(exprAtt);
ExprResult* exprResult = expr->evaluate(node, ps);
String data("expr debug: ");
expr->toString(data);
#if 0
// XXX DEBUG OUTPUT
cout << data << endl;
#endif
data.clear();
#if 0
// XXX DEBUG OUTPUT
cout << "result: ";
#endif
if ( exprResult ) {
switch ( exprResult->getResultType() ) {
case ExprResult::NODESET:
#if 0
// XXX DEBUG OUTPUT
cout << "#NodeSet - ";
#endif
default:
exprResult->stringValue(data);
#if 0
// XXX DEBUG OUTPUT
cout << data;
#endif
break;
}
}
#if 0
// XXX DEBUG OUTPUT
cout << endl;
#endif
delete exprResult;
break;
}
//-- xsl:value-of
case XSLType::VALUE_OF :
{
String selectAtt = actionElement->getAttribute(SELECT_ATTR);
expr = ps->getExpr(actionElement, ProcessorState::SelectAttr);
if (!expr)
break;
Expr* expr = ps->getExpr(selectAtt);
ExprResult* exprResult = expr->evaluate(node, ps);
String value;
if ( !exprResult ) {
@ -1632,10 +1596,8 @@ void XSLTProcessor::processAction
#endif
break;
} //-- switch
ps->popAction();
} //-- end if (element)
//cout << "XSLTProcessor#processAction [exit]\n";
} //-- processAction
/**
@ -1821,9 +1783,12 @@ void XSLTProcessor::processDefaultTemplate(Node* node,
case Node::ELEMENT_NODE :
case Node::DOCUMENT_NODE :
{
Expr* expr = ps->getPatternExpr("node()");
ExprResult* exprResult = expr->evaluate(node, ps);
if ( exprResult->getResultType() != ExprResult::NODESET ) {
if (!mNodeExpr)
break;
ExprResult* exprResult = mNodeExpr->evaluate(node, ps);
if (!exprResult ||
exprResult->getResultType() != ExprResult::NODESET) {
notifyError("None-nodeset returned while processing default template");
delete exprResult;
return;
@ -1941,9 +1906,10 @@ ExprResult* XSLTProcessor::processVariable
}
//-- check for select attribute
Attr* attr = xslVariable->getAttributeNode(SELECT_ATTR);
if ( attr ) {
Expr* expr = ps->getExpr(attr->getValue());
if (xslVariable->hasAttr(txXSLTAtoms::select, kNameSpaceID_None)) {
Expr* expr = ps->getExpr(xslVariable, ProcessorState::SelectAttr);
if (!expr)
return new StringResult("unable to process variable");
return expr->evaluate(node, ps);
}
else if (xslVariable->hasChildNodes()) {
@ -1958,7 +1924,7 @@ ExprResult* XSLTProcessor::processVariable
return nodeSet;
}
else {
return new StringResult("");
return new StringResult("");
}
} //-- processVariable
@ -2113,7 +2079,9 @@ XSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM,
Document* resultDocument = new Document(aOutputDoc);
//-- create a new ProcessorState
ProcessorState* ps = new ProcessorState(*sourceDocument, *xslDocument, *resultDocument);
ProcessorState* ps = new ProcessorState(sourceDocument,
xslDocument,
resultDocument);
//-- add error observers

View File

@ -236,6 +236,11 @@ private:
* Named Map for quick reference to XSL Types
**/
NamedMap xslTypes;
/*
* Used as default expression for some elements
*/
Expr* mNodeExpr;
/**
* Binds the given Variable
@ -412,8 +417,7 @@ public:
VARIABLE,
WHEN,
WITH_PARAM,
MESSAGE,
EXPR_DEBUG // temporary, used for debugging
MESSAGE
};
XSLType(const XSLType& xslType);

View File

@ -43,9 +43,12 @@
/*
* Creates a new DocumentFunctionCall.
*/
DocumentFunctionCall::DocumentFunctionCall(ProcessorState* aPs) : FunctionCall(DOCUMENT_FN)
DocumentFunctionCall::DocumentFunctionCall(ProcessorState* aPs,
Node* aDefResolveNode)
: FunctionCall(DOCUMENT_FN)
{
mProcessorState = aPs;
mDefResolveNode = aDefResolveNode;
}
/*
@ -118,8 +121,8 @@ ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs)
String uriStr;
exprResult1->stringValue(uriStr);
if (!baseURISet) {
Node* xsltElement = mProcessorState->peekAction();
nodeSet->add(mProcessorState->retrieveDocument(uriStr, xsltElement->getBaseURI()));
nodeSet->add(mProcessorState->retrieveDocument(uriStr,
mDefResolveNode->getBaseURI()));
}
else {
nodeSet->add(mProcessorState->retrieveDocument(uriStr, baseURI));

View File

@ -48,7 +48,7 @@ public:
/**
* Creates a new document() function call
**/
DocumentFunctionCall(ProcessorState* aPs);
DocumentFunctionCall(ProcessorState* aPs, Node* aDefResolveNode);
/**
* Evaluates this Expr based on the given context node and processor state
@ -62,6 +62,7 @@ public:
private:
ProcessorState* mProcessorState;
Node* mDefResolveNode;
};
/*
@ -115,12 +116,11 @@ public:
/*
* Adds a match/use pair. Returns MB_FALSE if matchString or useString
* can't be parsed.
* @param aMatchString String to be parsed as match-pattern
* @param aUseString String to be parsed as use-expression
* @return MB_FALSE if matchString or useString can't be parsed
* MB_TRUE otherwise
* @param aMatch match-pattern
* @param aUse use-expression
* @return MB_FALSE if an error occured, MB_TRUE otherwise
*/
MBool addKey(const String& aMatchString, const String& aUseString);
MBool addKey(Pattern* aMatch, Expr* aUse);
private:
/*

View File

@ -104,9 +104,11 @@ txXSLKey::txXSLKey(ProcessorState* aPs)
txXSLKey::~txXSLKey()
{
ListIterator iter(&mKeys);
while (iter.hasNext()) {
iter.next();
delete (Key*)iter.remove();
Key* key;
while ((key = (Key*)iter.next())) {
delete key->matchPattern;
delete key->useExpr;
delete key;
}
} // ~txXSLKey
@ -139,23 +141,21 @@ const NodeSet* txXSLKey::getNodes(String& aKeyValue, Document* aDoc)
/*
* Adds a match/use pair. Returns MB_FALSE if matchString or useString
* can't be parsed.
* @param aMatchString String to be parsed as match-pattern
* @param aUseString String to be parsed as use-expression
* @return MB_FALSE if matchString or useString can't be parsed
* MB_TRUE otherwise
* @param aMatch match-pattern
* @param aUse use-expression
* @return MB_FALSE if an error occured, MB_TRUE otherwise
*/
MBool txXSLKey::addKey(const String& aMatchString, const String& aUseString)
MBool txXSLKey::addKey(Pattern* aMatch, Expr* aUse)
{
if (!aMatch || !aUse)
return MB_FALSE;
Key* key = new Key;
if (!key)
return MB_FALSE;
key->matchPattern = mProcessorState->getPatternExpr(aMatchString);
key->useExpr = mProcessorState->getExpr(aUseString);
if (!key->matchPattern || !key->useExpr) {
delete key;
return MB_FALSE;
}
key->matchPattern = aMatch;
key->useExpr = aUse;
mKeys.add(key);
return MB_TRUE;
} // addKey

View File

@ -50,7 +50,8 @@
#define DEFAULT_LANG "en"
txNodeSorter::txNodeSorter(ProcessorState* aPs) : mPs(aPs),
mNKeys(0)
mNKeys(0),
mDefaultExpr(0)
{
}
@ -62,6 +63,7 @@ txNodeSorter::~txNodeSorter()
delete key->mComparator;
delete key;
}
delete mDefaultExpr;
}
MBool txNodeSorter::addSortElement(Element* aSortElement,
@ -77,13 +79,17 @@ MBool txNodeSorter::addSortElement(Element* aSortElement,
String attrValue;
// Select
Attr* attr = aSortElement->getAttributeNode(SELECT_ATTR);
if (attr)
attrValue = attr->getValue();
else
attrValue = ".";
key->mExpr = mPs->getExpr(attrValue);
if (aSortElement->getAttributeNode(SELECT_ATTR))
key->mExpr = mPs->getExpr(aSortElement, ProcessorState::SelectAttr);
else {
if (!mDefaultExpr) {
String expr(".");
ExprParser parser;
mDefaultExpr = parser.createExpr(expr);
}
key->mExpr = mDefaultExpr;
}
if (!key->mExpr) {
// XXX ErrorReport: Out of memory
delete key;

View File

@ -92,6 +92,7 @@ private:
txList mSortKeys;
ProcessorState* mPs;
int mNKeys;
Expr* mDefaultExpr;
};
#endif