Combining Michael E2's answer to another question, that redefines XMLElement, and MarcoB's answer above, here is another approach.
To get the Wolfram expression of the messy XML that will recreate the original Wolfram expression (there is probably a better way):
ImportString[ExportString[Hold[Times[a, Rational[1, -2], "test"]], "XML"], "XML"]
This results in:
XMLObject["Document"][{XMLObject["Declaration"]["Version" -> "1.0"],
XMLObject["Doctype"]["Expression",
"System" -> "http://www.wolfram.com/XML/notebookml1.dtd"]},
XMLElement[
"Expression", {{"http://www.w3.org/2000/xmlns/", "mathematica"} ->
"http://www.wolfram.com/XML/", {"http://www.w3.org/2000/xmlns/",
"xmlns"} -> "http://www.wolfram.com/XML/"}, {XMLElement[
"Function", {}, {XMLElement["Symbol", {}, {"Hold"}],
XMLElement[
"Function", {}, {XMLElement["Symbol", {}, {"Times"}],
XMLElement["Symbol", {}, {"a"}],
XMLElement[
"Function", {}, {XMLElement["Symbol", {}, {"Rational"}],
XMLElement["Number", {}, {"1"}],
XMLElement["Number", {}, {"-2"}]}],
XMLElement["String", {}, {"test"}]}]}]}], {}, "Valid" -> True]
Here is a Block that redefines XMLElement to clean up the Wolfram XML, by taking out the Expression, the Hold, and the Functions, and changing Number to Integer. (The XML expression just sits at the bottom - no function call needed):
x1 = Block[{ XMLElement, symbolName},
(* use block to temporarily redefine XMLElement *)
symbolName[element : XMLElement["Symbol", attributes_, children_List]] :=
First[children];
XMLElement["Expression", attributes_, {child_}] := child;
XMLElement["Function", attributes_, children_List] :=
Module[{name},
name = symbolName[First[children]];
XMLElement[name, attributes, Rest[children]]];
XMLElement["Hold", attributes_, {child_}] := child;
XMLElement["Number", attributes_, {child_}] :=
Module[{number, name},
number = Interpreter["Number"][child];
name = ToString@Head@number;
XMLElement[name, attributes, child]];
ImportString[
ExportString[Hold[Times[a, Rational[1, -2], "test"]], "XML"],
"XML"]
];
Wolfram complains about bad XML, but still returns:
XMLObject["Document"][{XMLObject["Declaration"]["Version" -> "1.0"],
XMLObject["Doctype"]["Expression",
"System" -> "http://www.wolfram.com/XML/notebookml1.dtd"]},
XMLElement[
"Times", {}, {XMLElement["Symbol", {}, {"a"}],
XMLElement[
"Rational", {}, {XMLElement["Integer", {}, {"1"}],
XMLElement["Integer", {}, {"-2"}]}],
XMLElement["String", {}, {"test"}]}], {}, "Valid" -> False]
To make it readable, here is an indenting print engine:
(* indenting print engine *)
Remove[new, contents, cr, tab, inc, dec, in, open, close, string,
indent, initial, pp];
initial = "";
string = initial;
indent = 0;
(* always return the symbol, so can chain *)
pp[new] := Module[{}, string = initial; indent = 0; pp];
pp[contents] := string;
pp[s_String] := Module[{x}, string = string <> s; pp];
pp[cr] := pp["\n"];
pp[tab] := pp["\t"];
(* inc increases indent; dec decreases indent *)
pp[inc] := Module[{}, indent = indent + 1; pp];
pp[dec] := Module[{}, indent = Max[indent - 1, 0]; pp];
(* in makes the indent *)
pp[in] := If[indent > 0, pp[StringRepeat["\t", indent]], pp]
(* add XML to the engine *)
initial = "<?xml version='1.0'?>\n";
pp[open, name_String] := pp["<"][name][">"]
pp[close, name_String] := pp["</"][name][">"]
pp[x : XMLObject["Document"][a_, body_, rest__]] := pp[body];
pp[x : XMLElement[name_String, attributes_, {text_String}]] :=
Module[{}, pp[open, name][text][close, name]]
pp[x : XMLElement[name_String, attributes_, children_List]] :=
Module[{},
pp[open, name][inc];
Scan[(pp[cr][in][#]) &, children];
pp[dec][cr][in][close, name]]
To print x1:
pp[new][x1][contents]
Which results in:
"<?xml version='1.0'?>
<Times>
<Symbol>a</Symbol>
<Rational>
<Integer>1</Integer>
<Integer>-2</Integer>
</Rational>
<String>test</String>
</Times>"
TreeForm
be somewhat in the ballpark? Consider also thatTreeForm
takes the same options asTreePlot
, so it may be reasonably customizable. $\endgroup$("test") / z
. Maybe you could expand on what you want to do with this "folder structure form". $\endgroup$Times["test", Power[z, -1]]
? I can''t tell if you misunderstand the example or just don't get the intent of converting it to a directory structure. $\endgroup$Export[expr,"MathML","Content" -> True, "Presentation" -> False]
. $\endgroup$