Right now I'm trying to make a recursive function that takes an HTML document tree and returns a string representing formatted CSS using only children (>
) operators. I'll explain it further and maybe you can help me where I'm stuck. At least please give me some hints or ideas.
So the idea is to go from something like
body
/ \
div div
/ \ / \ \
h1 p p ul div
/ \
li li
to
div
div > h1
div > p
div > p
div > ul
div > ul > li
div > ul > li
div > div
or, if you prefer,
"div\n\t div > h1\n\tdiv > p\n\tdiv > p\n\tdiv > ul\n\t\tdiv > ul > li\n\t\tdiv > ul > li\n\tdiv > div"
I already have a procedure that gets the body
and the tree growing from it. The 3 functions I'll need are members of an object called XMLNode
getChildNode(int k)
returns the XMLNode
object that is the k
th child. If none exists, then the object return has propertyisEmpty()
.getName()
returns the name of the node as a string-like object which can be cast into a string.So my attempt at writing a procedure that does what I need is calling
std::cout << tree2CSS(bodyNode);
where the function tree2CSS
is implemented like
std::string tree2CSS(XMLNode & rootNode, unsigned depth = 0)
{
int i = 1;
XMLNode childNode = rootNode.getChildNode(i);
std::string accumCSS;
while (!childNode.isEmpty())
{
std::string tabs(depth, '\t');
accumCSS.append("\n" + tabs);
if (depth > 0) accumCSS.append(" > ");
accumCSS.append((std::string)childNode.getName() + tree2CSS(childNode, depth + 1));
childNode = rootNode.getChildNode(++i);
}
return accumCSS;
}
Problem is, that procedure isn't working and I can't figure out why. Can anyone help me?
You want to print the whole ancestry for each element, so you must somehow keep track of all parents, not just the depth.
I think that prining is better handled once for each element outside the loop and the loop is just for visiting the children.
Here's an alternative implementation:
std::string tree2CSS_(XMLNode& rootNode, std::vector<std::string>& pred)
{
std::string accumCSS(pred.size(), '\t');
std::string name = rootNode.getName();
for (size_t i = 0; i < pred.size(); ++i) {
accumCSS += pred[i] + " > ";
}
accumCSS += name + "\n";
size_t i = 0;
XMLNode& childNode = rootNode.getChildNode(i);
pred.push_back(name);
while (!childNode.isEmpty()) {
accumCSS.append(tree2CSS_(childNode, pred));
childNode = rootNode.getChildNode(++i);
}
pred.pop_back();
return accumCSS;
}
std::string tree2CSS(XMLNode& rootNode)
{
std::vector<std::string> pred;
return tree2CSS_(rootNode, pred);
}
I've used a vector of preceding strings here, whose size if of course the recursion depth. The iplementation is divided into a front-end function, which provides the vector, and the recursive implementation.
This implementation prints the body node and also prepends the body to all CSS declarators. If you want to skip the top-most node, loop over body's children in the front-end function.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments