mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-09 08:48:07 +00:00
Implementation of the xsl:apply-imports instruction.
b=94002 r=peterv sr=jst
This commit is contained in:
parent
614453083c
commit
c2521b6587
@ -425,22 +425,60 @@ List* ProcessorState::getImportFrames()
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds a template for the given Node. Only templates with
|
||||
* a mode attribute equal to the given mode will be searched.
|
||||
* Find template in specified mode matching the supplied node
|
||||
* @param aNode node to find matching template for
|
||||
* @param aMode mode of the template
|
||||
* @param aImportFrame out-param, is set to the ImportFrame containing
|
||||
* the found template
|
||||
* @return root-node of found template, null if none is found
|
||||
*/
|
||||
Node* ProcessorState::findTemplate(Node* aNode,
|
||||
Node* aContext,
|
||||
const String& aMode)
|
||||
const String& aMode,
|
||||
ImportFrame** aImportFrame)
|
||||
{
|
||||
return findTemplate(aNode, aMode, 0, aImportFrame);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find template in specified mode matching the supplied node. Only search
|
||||
* templates imported by a specific ImportFrame
|
||||
* @param aNode node to find matching template for
|
||||
* @param aMode mode of the template
|
||||
* @param aImportedBy seach only templates imported by this ImportFrame,
|
||||
* or null to search all templates
|
||||
* @param aImportFrame out-param, is set to the ImportFrame containing
|
||||
* the found template
|
||||
* @return root-node of found template, null if none is found
|
||||
*/
|
||||
Node* ProcessorState::findTemplate(Node* aNode,
|
||||
const String& aMode,
|
||||
ImportFrame* aImportedBy,
|
||||
ImportFrame** aImportFrame)
|
||||
{
|
||||
NS_ASSERTION(aImportFrame, "missing ImportFrame pointer");
|
||||
NS_ASSERTION(aNode, "missing node");
|
||||
|
||||
if (!aNode)
|
||||
return 0;
|
||||
|
||||
Node* matchTemplate = 0;
|
||||
double currentPriority = Double::NEGATIVE_INFINITY;
|
||||
ImportFrame* frame;
|
||||
ImportFrame* endFrame = 0;
|
||||
txListIterator frameIter(&mImportFrames);
|
||||
|
||||
while (!matchTemplate && (frame = (ImportFrame*)frameIter.next())) {
|
||||
if (aImportedBy) {
|
||||
ImportFrame* curr = (ImportFrame*)frameIter.next();
|
||||
while (curr != aImportedBy)
|
||||
curr = (ImportFrame*)frameIter.next();
|
||||
|
||||
endFrame = aImportedBy->mFirstNotImported;
|
||||
}
|
||||
|
||||
ImportFrame* frame;
|
||||
while (!matchTemplate &&
|
||||
(frame = (ImportFrame*)frameIter.next()) &&
|
||||
frame != endFrame) {
|
||||
|
||||
// get templatelist for this mode
|
||||
txList* templates;
|
||||
templates = (txList*)frame->mMatchableTemplates.get(aMode);
|
||||
@ -448,6 +486,7 @@ Node* ProcessorState::findTemplate(Node* aNode,
|
||||
if (templates) {
|
||||
txListIterator templateIter(templates);
|
||||
|
||||
// Find template with highest priority
|
||||
MatchableTemplate* templ;
|
||||
while ((templ = (MatchableTemplate*)templateIter.next())) {
|
||||
String priorityAttr;
|
||||
@ -463,14 +502,15 @@ Node* ProcessorState::findTemplate(Node* aNode,
|
||||
}
|
||||
else {
|
||||
tmpPriority = templ->mMatch->getDefaultPriority(aNode,
|
||||
aContext,
|
||||
0,
|
||||
this);
|
||||
}
|
||||
|
||||
if (tmpPriority >= currentPriority &&
|
||||
templ->mMatch->matches(aNode, aContext, this)) {
|
||||
templ->mMatch->matches(aNode, 0, this)) {
|
||||
|
||||
matchTemplate = templ->mTemplate;
|
||||
*aImportFrame = frame;
|
||||
currentPriority = tmpPriority;
|
||||
}
|
||||
}
|
||||
@ -478,7 +518,23 @@ Node* ProcessorState::findTemplate(Node* aNode,
|
||||
}
|
||||
|
||||
return matchTemplate;
|
||||
} //-- findTemplate
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets current template rule
|
||||
*/
|
||||
ProcessorState::TemplateRule* ProcessorState::getCurrentTemplateRule()
|
||||
{
|
||||
return mCurrentTemplateRule;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets current template rule
|
||||
*/
|
||||
void ProcessorState::setCurrentTemplateRule(TemplateRule* aTemplateRule)
|
||||
{
|
||||
mCurrentTemplateRule = aTemplateRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the AttributeSet associated with the given name
|
||||
@ -1274,9 +1330,10 @@ void ProcessorState::initialize() {
|
||||
decimalFormats.setObjectDeletion(MB_TRUE);
|
||||
}
|
||||
|
||||
ProcessorState::ImportFrame::ImportFrame()
|
||||
ProcessorState::ImportFrame::ImportFrame(ImportFrame* aFirstNotImported)
|
||||
{
|
||||
mNamedAttributeSets.setObjectDeletion(MB_TRUE);
|
||||
mFirstNotImported = aFirstNotImported;
|
||||
}
|
||||
|
||||
ProcessorState::ImportFrame::~ImportFrame()
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
*/
|
||||
class ImportFrame {
|
||||
public:
|
||||
ImportFrame();
|
||||
ImportFrame(ImportFrame* aFirstNotImported);
|
||||
~ImportFrame();
|
||||
|
||||
// Map of named templates
|
||||
@ -92,16 +92,16 @@ public:
|
||||
// Map of named attribute sets
|
||||
NamedMap mNamedAttributeSets;
|
||||
|
||||
// ImportFrame which is the first one *not* imported by this frame
|
||||
ImportFrame* mFirstNotImported;
|
||||
|
||||
// The following stuff is missing here:
|
||||
|
||||
// ImportFrame(?) for xsl:apply-imports
|
||||
// Nametests for xsl:strip-space and xsl:preserve-space
|
||||
// Namespace aliases (xsl:namespace-alias)
|
||||
// Named attribute sets
|
||||
// Toplevel variables/parameters
|
||||
// Output specifier (xsl:output)
|
||||
};
|
||||
// To be able to do some cleaning up in destructor
|
||||
friend class ImportFrame;
|
||||
|
||||
/*
|
||||
@ -234,17 +234,52 @@ public:
|
||||
**/
|
||||
List* getImportFrames();
|
||||
|
||||
/**
|
||||
* Finds a template for the given Node. Only templates without
|
||||
* a mode attribute will be searched.
|
||||
**/
|
||||
Element* findTemplate(Node* node, Node* context);
|
||||
/*
|
||||
* Find template in specified mode matching the supplied node
|
||||
* @param aNode node to find matching template for
|
||||
* @param aMode mode of the template
|
||||
* @param aImportFrame out-param, is set to the ImportFrame containing
|
||||
* the found template
|
||||
* @return root-node of found template, null if none is found
|
||||
*/
|
||||
Node* findTemplate(Node* aNode,
|
||||
const String& aMode,
|
||||
ImportFrame** aImportFrame);
|
||||
|
||||
/*
|
||||
* Finds a template for the given Node. Only templates with
|
||||
* a mode attribute equal to the given mode will be searched.
|
||||
* Find template in specified mode matching the supplied node. Only search
|
||||
* templates imported by a specific ImportFrame
|
||||
* @param aNode node to find matching template for
|
||||
* @param aMode mode of the template
|
||||
* @param aImportedBy seach only templates imported by this ImportFrame,
|
||||
* or null to search all templates
|
||||
* @param aImportFrame out-param, is set to the ImportFrame containing
|
||||
* the found template
|
||||
* @return root-node of found template, null if none is found
|
||||
*/
|
||||
Node* findTemplate(Node* aNode, Node* aContext, const String& aMode);
|
||||
Node* findTemplate(Node* aNode,
|
||||
const String& aMode,
|
||||
ImportFrame* aImportedBy,
|
||||
ImportFrame** aImportFrame);
|
||||
|
||||
/*
|
||||
* Struct holding information about a current template rule
|
||||
*/
|
||||
struct TemplateRule {
|
||||
ImportFrame* mFrame;
|
||||
const String* mMode;
|
||||
NamedMap* mParams;
|
||||
};
|
||||
|
||||
/*
|
||||
* Gets current template rule
|
||||
*/
|
||||
TemplateRule* getCurrentTemplateRule();
|
||||
|
||||
/*
|
||||
* Sets current template rule
|
||||
*/
|
||||
void setCurrentTemplateRule(TemplateRule* aTemplateRule);
|
||||
|
||||
/**
|
||||
* Determines if the given XSL node allows Whitespace stripping
|
||||
@ -458,6 +493,11 @@ private:
|
||||
*/
|
||||
Map mPatternHashes[2];
|
||||
|
||||
/*
|
||||
* Current template rule
|
||||
*/
|
||||
TemplateRule* mCurrentTemplateRule;
|
||||
|
||||
Element* mXPathParseContext;
|
||||
Stack nodeSetStack;
|
||||
Document* mSourceDocument;
|
||||
|
@ -106,6 +106,7 @@ XSLTProcessor::XSLTProcessor() {
|
||||
|
||||
//-- create XSL element types
|
||||
xslTypes.setObjectDeletion(MB_TRUE);
|
||||
xslTypes.put(APPLY_IMPORTS, new XSLType(XSLType::APPLY_IMPORTS));
|
||||
xslTypes.put(APPLY_TEMPLATES, new XSLType(XSLType::APPLY_TEMPLATES));
|
||||
xslTypes.put(ATTRIBUTE, new XSLType(XSLType::ATTRIBUTE));
|
||||
xslTypes.put(ATTRIBUTE_SET, new XSLType(XSLType::ATTRIBUTE_SET));
|
||||
@ -502,11 +503,22 @@ void XSLTProcessor::processTopLevel(Document* aSource,
|
||||
element->getBaseURI(),
|
||||
href);
|
||||
|
||||
importFrame->addAfter(new ProcessorState::ImportFrame);
|
||||
importFrame->next();
|
||||
// Create a new ImportFrame with correct firstNotImported
|
||||
ProcessorState::ImportFrame *nextFrame, *newFrame;
|
||||
nextFrame =
|
||||
(ProcessorState::ImportFrame*)importFrame->next();
|
||||
newFrame = new ProcessorState::ImportFrame(nextFrame);
|
||||
if (!newFrame) {
|
||||
// XXX ErrorReport: out of memory
|
||||
break;
|
||||
}
|
||||
|
||||
// Insert frame and process stylesheet
|
||||
importFrame->addBefore(newFrame);
|
||||
importFrame->previous();
|
||||
processInclude(href, aSource, importFrame, aPs);
|
||||
|
||||
// Restore iterator to initial position
|
||||
importFrame->previous();
|
||||
|
||||
break;
|
||||
@ -762,14 +774,14 @@ Document* XSLTProcessor::process
|
||||
//-------------------------------------------------------/
|
||||
|
||||
ListIterator importFrame(ps.getImportFrames());
|
||||
importFrame.addAfter(new ProcessorState::ImportFrame);
|
||||
importFrame.addAfter(new ProcessorState::ImportFrame(0));
|
||||
importFrame.next();
|
||||
processStylesheet(&xmlDocument, &xslDocument, &importFrame, &ps);
|
||||
|
||||
//----------------------------------------/
|
||||
//- Process root of XML source document -/
|
||||
//--------------------------------------/
|
||||
process(&xmlDocument, &xmlDocument, NULL_STRING, &ps);
|
||||
process(&xmlDocument, NULL_STRING, &ps);
|
||||
|
||||
//-- return result Document
|
||||
return result;
|
||||
@ -808,14 +820,14 @@ void XSLTProcessor::process
|
||||
//-------------------------------------------------------/
|
||||
|
||||
ListIterator importFrame(ps.getImportFrames());
|
||||
importFrame.addAfter(new ProcessorState::ImportFrame);
|
||||
importFrame.addAfter(new ProcessorState::ImportFrame(0));
|
||||
importFrame.next();
|
||||
processStylesheet(&xmlDocument, &xslDocument, &importFrame, &ps);
|
||||
|
||||
//----------------------------------------/
|
||||
//- Process root of XML source document -/
|
||||
//--------------------------------------/
|
||||
process(&xmlDocument, &xmlDocument, NULL_STRING, &ps);
|
||||
process(&xmlDocument, NULL_STRING, &ps);
|
||||
|
||||
print(*result, ps.getOutputFormat(), out);
|
||||
|
||||
@ -1029,17 +1041,14 @@ void XSLTProcessor::notifyError(String& errorMessage, ErrorObserver::ErrorLevel
|
||||
} //-- notifyError
|
||||
|
||||
void XSLTProcessor::process(Node* node,
|
||||
Node* context,
|
||||
const String& mode,
|
||||
ProcessorState* ps) {
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
Node* xslTemplate = ps->findTemplate(node, context, mode);
|
||||
if (xslTemplate)
|
||||
processTemplate(node, xslTemplate, ps);
|
||||
else
|
||||
processDefaultTemplate(node, ps, NULL_STRING);
|
||||
ProcessorState::ImportFrame *frame;
|
||||
Node* xslTemplate = ps->findTemplate(node, mode, &frame);
|
||||
processMatchedTemplate(xslTemplate, node, 0, NULL_STRING, frame, ps);
|
||||
} //-- process
|
||||
|
||||
void XSLTProcessor::processAction
|
||||
@ -1086,6 +1095,27 @@ void XSLTProcessor::processAction
|
||||
|
||||
switch ( getElementType(nodeName, ps) ) {
|
||||
|
||||
//-- xsl:apply-imports
|
||||
case XSLType::APPLY_IMPORTS :
|
||||
{
|
||||
ProcessorState::TemplateRule* curr;
|
||||
Node* xslTemplate;
|
||||
ProcessorState::ImportFrame *frame;
|
||||
|
||||
curr = ps->getCurrentTemplateRule();
|
||||
if (!curr) {
|
||||
String err("apply-imports not allowed here");
|
||||
ps->recieveError(err);
|
||||
break;
|
||||
}
|
||||
|
||||
xslTemplate = ps->findTemplate(node, *curr->mMode,
|
||||
curr->mFrame, &frame);
|
||||
processMatchedTemplate(xslTemplate, node, curr->mParams,
|
||||
*curr->mMode, frame, ps);
|
||||
|
||||
break;
|
||||
}
|
||||
//-- xsl:apply-templates
|
||||
case XSLType::APPLY_TEMPLATES :
|
||||
{
|
||||
@ -1129,18 +1159,14 @@ void XSLTProcessor::processAction
|
||||
NamedMap* actualParams = processParameters(actionElement, node, ps);
|
||||
|
||||
for (int i = 0; i < nodeSet->size(); i++) {
|
||||
ProcessorState::ImportFrame *frame;
|
||||
Node* currNode = nodeSet->get(i);
|
||||
Node* xslTemplate;
|
||||
xslTemplate = ps->findTemplate(currNode, node, mode);
|
||||
if (xslTemplate) {
|
||||
ps->pushCurrentNode(currNode);
|
||||
processTemplate(currNode, xslTemplate, ps, actualParams);
|
||||
ps->popCurrentNode();
|
||||
}
|
||||
else {
|
||||
processDefaultTemplate(currNode, ps, mode);
|
||||
}
|
||||
xslTemplate = ps->findTemplate(currNode, mode, &frame);
|
||||
processMatchedTemplate(xslTemplate, currNode,
|
||||
actualParams, mode, frame, ps);
|
||||
}
|
||||
|
||||
//-- remove nodeSet from context stack
|
||||
ps->getNodeSetStack()->pop();
|
||||
|
||||
@ -1370,6 +1396,11 @@ void XSLTProcessor::processAction
|
||||
}
|
||||
sorter.sortNodeSet(nodeSet);
|
||||
|
||||
// Set current template to null
|
||||
ProcessorState::TemplateRule *oldTemplate;
|
||||
oldTemplate = ps->getCurrentTemplateRule();
|
||||
ps->setCurrentTemplateRule(0);
|
||||
|
||||
for (int i = 0; i < nodeSet->size(); i++) {
|
||||
Node* currNode = nodeSet->get(i);
|
||||
ps->pushCurrentNode(currNode);
|
||||
@ -1377,7 +1408,9 @@ void XSLTProcessor::processAction
|
||||
ps->popCurrentNode();
|
||||
}
|
||||
|
||||
//-- remove nodeSet from context stack
|
||||
ps->setCurrentTemplateRule(oldTemplate);
|
||||
|
||||
// Remove nodeSet from context stack
|
||||
ps->getNodeSetStack()->pop();
|
||||
}
|
||||
else {
|
||||
@ -1766,6 +1799,32 @@ void XSLTProcessor::processTemplate(Node* node, Node* xslTemplate, ProcessorStat
|
||||
bindings->pop();
|
||||
} //-- processTemplate
|
||||
|
||||
void XSLTProcessor::processMatchedTemplate(Node* aXslTemplate,
|
||||
Node* aNode,
|
||||
NamedMap* aParams,
|
||||
const String& aMode,
|
||||
ProcessorState::ImportFrame* aFrame,
|
||||
ProcessorState* aPs)
|
||||
{
|
||||
if (aXslTemplate) {
|
||||
ProcessorState::TemplateRule *oldTemplate, newTemplate;
|
||||
oldTemplate = aPs->getCurrentTemplateRule();
|
||||
newTemplate.mFrame = aFrame;
|
||||
newTemplate.mMode = &aMode;
|
||||
newTemplate.mParams = aParams;
|
||||
aPs->setCurrentTemplateRule(&newTemplate);
|
||||
|
||||
aPs->pushCurrentNode(aNode);
|
||||
processTemplate(aNode, aXslTemplate, aPs, aParams);
|
||||
aPs->popCurrentNode();
|
||||
|
||||
aPs->setCurrentTemplateRule(oldTemplate);
|
||||
}
|
||||
else {
|
||||
processDefaultTemplate(aNode, aPs, aMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the default template for the specified node
|
||||
* @param node context node
|
||||
@ -1804,15 +1863,11 @@ void XSLTProcessor::processDefaultTemplate(Node* node,
|
||||
ps->getNodeSetStack()->push(nodeSet);
|
||||
for (int i = 0; i < nodeSet->size(); i++) {
|
||||
Node* currNode = nodeSet->get(i);
|
||||
Node* xslTemplate = ps->findTemplate(currNode, node, mode);
|
||||
if (xslTemplate) {
|
||||
ps->pushCurrentNode(currNode);
|
||||
processTemplate(currNode, xslTemplate, ps, NULL);
|
||||
ps->popCurrentNode();
|
||||
}
|
||||
else {
|
||||
processDefaultTemplate(currNode, ps, mode);
|
||||
}
|
||||
|
||||
ProcessorState::ImportFrame *frame;
|
||||
Node* xslTemplate = ps->findTemplate(currNode, mode, &frame);
|
||||
processMatchedTemplate(xslTemplate, currNode, 0, mode, frame,
|
||||
ps);
|
||||
}
|
||||
//-- remove nodeSet from context stack
|
||||
ps->getNodeSetStack()->pop();
|
||||
@ -2094,14 +2149,14 @@ XSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM,
|
||||
//- index templates and process top level xsl elements -/
|
||||
//------------------------------------------------------/
|
||||
ListIterator importFrame(ps->getImportFrames());
|
||||
importFrame.addAfter(new ProcessorState::ImportFrame);
|
||||
importFrame.addAfter(new ProcessorState::ImportFrame(0));
|
||||
importFrame.next();
|
||||
processStylesheet(sourceDocument, xslDocument, &importFrame, ps);
|
||||
|
||||
//---------------------------------------/
|
||||
//- Process root of XML source document -/
|
||||
//---------------------------------------/
|
||||
process(sourceNode, sourceNode, NULL_STRING, ps);
|
||||
process(sourceNode, NULL_STRING, ps);
|
||||
|
||||
// XXX Hack, ProcessorState::addToResultTree should do the right thing
|
||||
// for adding several consecutive text nodes
|
||||
|
@ -313,7 +313,6 @@ private:
|
||||
#endif
|
||||
|
||||
void process(Node* node,
|
||||
Node* context,
|
||||
const String& mode,
|
||||
ProcessorState* ps);
|
||||
|
||||
@ -336,6 +335,12 @@ private:
|
||||
void processTemplate(Node* node, Node* xslTemplate, ProcessorState* ps, NamedMap* actualParams = NULL);
|
||||
void processTemplateParams(Node* xslTemplate, Node* context, ProcessorState* ps, NamedMap* actualParams);
|
||||
|
||||
void processMatchedTemplate(Node* aXslTemplate,
|
||||
Node* aNode,
|
||||
NamedMap* aParams,
|
||||
const String& aMode,
|
||||
ProcessorState::ImportFrame* aFrame,
|
||||
ProcessorState* aPs);
|
||||
/**
|
||||
* Invokes the default template for the specified node
|
||||
* @param node context node
|
||||
|
Loading…
x
Reference in New Issue
Block a user