This removes the need for the sortByDocumentOrder function. b=85893 r=Pike rs=jag git-svn-id: svn://10.0.0.236/trunk@113703 18797224-902f-48f8-a5cc-f745e15eee43
188 lines
5.8 KiB
C++
188 lines
5.8 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is TransforMiiX XSLT processor.
|
|
*
|
|
* The Initial Developer of the Original Code is The MITRE Corporation.
|
|
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
|
|
*
|
|
* Portions created by Keith Visco as a Non MITRE employee,
|
|
* (C) 1999 Keith Visco. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Keith Visco, kvisco@ziplink.net
|
|
* -- original author.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* Numbering methods
|
|
**/
|
|
|
|
#include "Numbering.h"
|
|
#include "Names.h"
|
|
#include "txAtoms.h"
|
|
|
|
void Numbering::doNumbering(Element* xslNumber, String& dest, Node* context,
|
|
ProcessorState* ps)
|
|
{
|
|
if (!xslNumber)
|
|
return;
|
|
|
|
int* counts = 0;
|
|
int nbrOfCounts = 0;
|
|
|
|
String valueAttr;
|
|
xslNumber->getAttr(txXSLTAtoms::value, kNameSpaceID_None,
|
|
valueAttr);
|
|
//-- check for expr
|
|
if (!valueAttr.isEmpty()) {
|
|
Expr* expr = ps->getExpr(xslNumber, ProcessorState::ValueAttr);
|
|
if (!expr)
|
|
return;
|
|
nbrOfCounts = 1;
|
|
counts = new int[1];
|
|
ExprResult* result = expr->evaluate(context, ps);
|
|
double dbl = result->numberValue();
|
|
delete result;
|
|
counts[0] = (int)dbl;
|
|
}
|
|
else if (context) {
|
|
|
|
//-- create count expression
|
|
|
|
String countAttr;
|
|
xslNumber->getAttr(txXSLTAtoms::count, kNameSpaceID_None,
|
|
countAttr);
|
|
|
|
Pattern* countPattern;
|
|
MBool ownsPattern;
|
|
|
|
if (!countAttr.isEmpty()) {
|
|
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('@');
|
|
countAttr.append(context->getNodeName());
|
|
break;
|
|
case Node::ELEMENT_NODE:
|
|
countAttr.append(context->getNodeName());
|
|
break;
|
|
case Node::CDATA_SECTION_NODE :
|
|
case Node::TEXT_NODE :
|
|
countAttr.append("text()");
|
|
break;
|
|
case Node::COMMENT_NODE :
|
|
countAttr.append("comment()");
|
|
break;
|
|
case Node::PROCESSING_INSTRUCTION_NODE :
|
|
countAttr.append("processing-instruction()");
|
|
break;
|
|
default:
|
|
countAttr.append("node()[false()]"); //-- for now
|
|
break;
|
|
}
|
|
ExprParser parser;
|
|
countPattern = parser.createPattern(countAttr);
|
|
ownsPattern = MB_TRUE;
|
|
}
|
|
if (!countPattern) {
|
|
delete counts;
|
|
return;
|
|
}
|
|
|
|
NodeSet* nodes = 0;
|
|
int cnum = 0;
|
|
|
|
String level;
|
|
xslNumber->getAttr(txXSLTAtoms::level, kNameSpaceID_None,
|
|
level);
|
|
String fromAttr;
|
|
xslNumber->getAttr(txXSLTAtoms::from, kNameSpaceID_None,
|
|
fromAttr);
|
|
PatternExpr* from = 0;
|
|
|
|
if (MULTIPLE_VALUE.isEqual(level))
|
|
nodes = getAncestorsOrSelf(countPattern,
|
|
from,
|
|
context,
|
|
ps,
|
|
MB_FALSE);
|
|
//else if (ANY_VALUE.isEqual(level))
|
|
// nodes = getAnyPreviousNodes(countExpr, context, ps);
|
|
else
|
|
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(countPattern, nodes->get(i), ps);
|
|
}
|
|
delete nodes;
|
|
if (ownsPattern)
|
|
delete countPattern;
|
|
}
|
|
//-- format counts
|
|
for ( int i = 0; i < nbrOfCounts; i++) {
|
|
Double::toString(counts[i], dest);
|
|
}
|
|
delete counts;
|
|
} //-- doNumbering
|
|
|
|
int Numbering::countPreceedingSiblings
|
|
(PatternExpr* patternExpr, Node* context, ProcessorState* ps)
|
|
{
|
|
int count = 1;
|
|
|
|
if (!context) return 0;
|
|
|
|
Node* sibling = context;
|
|
while ((sibling = sibling->getPreviousSibling())) {
|
|
if (patternExpr->matches(sibling, sibling, ps))
|
|
++count;
|
|
}
|
|
return count;
|
|
} //-- countPreceedingSiblings
|
|
|
|
NodeSet* Numbering::getAncestorsOrSelf
|
|
( PatternExpr* countExpr,
|
|
PatternExpr* from,
|
|
Node* context,
|
|
ProcessorState* ps,
|
|
MBool findNearest)
|
|
{
|
|
NodeSet* nodeSet = new NodeSet();
|
|
Node* parent = context;
|
|
while ((parent) && (parent->getNodeType() == Node::ELEMENT_NODE))
|
|
{
|
|
if ((from) && from->matches(parent, parent->getParentNode(), ps)) break;
|
|
|
|
if (countExpr->matches(parent, parent->getParentNode(), ps)) {
|
|
nodeSet->append(parent);
|
|
if (findNearest) break;
|
|
}
|
|
parent = parent->getParentNode();
|
|
}
|
|
return nodeSet;
|
|
} //-- fromAncestorsOrSelf
|