mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Bug 95779 - Key cached expressions and patterns on node they appear in rather then string.
r=Pike sr=jst
This commit is contained in:
parent
9dbad9b635
commit
79768f9dfc
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
//--------------------/
|
||||
|
@ -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
|
||||
|
@ -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++) {
|
||||
|
@ -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 ) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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:
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -92,6 +92,7 @@ private:
|
||||
txList mSortKeys;
|
||||
ProcessorState* mPs;
|
||||
int mNKeys;
|
||||
Expr* mDefaultExpr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user