XML Tree Presentation


  • 3
    M

    Let's say you have a xml file, the structure looks like this:

    <Story>
      <id>1234</id>
      <Snaps>
          <Snap></Snap>
          <Snap></Snap>
          <Snap></Snap>
          <Snap></Snap>
      </Snaps>
    <Story>
    

    We have a xml parser converting this xml to a csv format, open means open tag, close means close tag, inner is just inner text.

    [
      "open,story",
      "open,id",
      "inner,1234",
      "close,id",
      "open,snaps",
      "open,snap",
      "close,snap",
      "open,snap",
      "close,snap",
      "open,snap",
      "close,snap",
      "open,snap",
      "close,snap",
      "close,snaps",
      "close,story"
    ]
    

    Given this csv input, please use tree structure to present this.


  • 0
    I

    How did you do the problem?


  • 0
    N

    @man123v1 I'm not really sure what this question is asking. Could you clarify a bit more?


  • 0
    S

    I think the question is asking to create an XML tree using the csv data. Simply make a tree where on "open" you make a child node; on "inner" assign the value for that node and on "close" traverse back to the parent.


  • 0
    M

    @siddharthshah52 +1 on the definition


  • 0
    S
    let cmdsToTree = (lines) => {
    
        let root = {name: "root", children:[]};
        let parents = [root];
    
        lines.forEach( line => {
            let [command,param] = line.split(',');
            let node = null;
            switch(command) {
                case "open": 
                    node = {name: param, children: []};
                    parents[parents.length-1].children.push(node);
                    parents.push(node);
                break;
                case "close":
                    parents.pop();
                break;
                case "inner":
                    node = {text: param, children: []};
                    parents[parents.length-1].children.push(node);
                break;
            }
        });
    
        return root.children[0];
    }
    
    
    let print = (node, depth) => {
        let spaces = new Array(depth+1).join(' ');
        if(node.name) {
            console.log(`${spaces}<${node.name}>`);
        }else {
            console.log(`${spaces} ${node.text}`);
        }
    
        node.children.forEach( child => print(child, depth+4));
    
        if(node.name) {
            console.log(`${spaces}</${node.name}>`);
        }
    }
    
    let cmds = [
      "open,story",
      "open,id",
      "inner,1234",
      "close,id",
      "open,snaps",
      "open,snap",
      "close,snap",
      "open,snap",
      "close,snap",
      "open,snap",
      "close,snap",
      "open,snap",
      "close,snap",
      "close,snaps",
      "close,story"
    ];
    
    let tree = cmdsToTree(cmds);
    print(tree, 0);
    

  • 0
    M

    Here is my java solution. I think the definition of dom node need to use composite design pattern. The printing process looks like one of the question I did before involving nestedInteger. If you find anything wrong, please let me know.

    # code block
    package other;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Stack;
    
    public class S_xmlParser {
    	public DomTree parse(List<String> input) {
    		Stack<TagNode> stack = new Stack<>();
    		DomTree last = null;
    		for (String parts : input) {
    			String[] part = parts.split(",");
    			if (part[0].equals("open")) {
    				TagNode tag = new TagNode();
    				tag.start = "<" + part[1] + ">";
    				if (!stack.isEmpty()) {
    					stack.peek().children.add(tag);
    				}
    				stack.push(tag);
    			} else if (part[0].equals("close")) {
    				if (!stack.isEmpty()) {
    					TagNode tag = stack.pop();
    					tag.end = "</" + part[1] + ">";
    					last = tag;
    				}
    			} else {
    				ContentNode content = new ContentNode();
    				content.content = part[1];
    				stack.peek().children.add(content);
    			}
    		}
    		
    		return last;
    	}
    
    	public static void main(String[] args) {
    		S_xmlParser parser = new S_xmlParser();
    		List<String> input = new ArrayList<>(Arrays.asList("open,story", "open,id", "inner,1234", "close,id",
    				"open,snaps", "open,snap", "close,snap", "open,snap", "close,snap", "open,snap", "close,snap",
    				"open,snap", "close,snap", "close,snaps", "close,story"));
    		DomTree dom = parser.parse(input);
    		print(dom);
    	}
    
    	private static void print(DomTree dom) {
    		if (dom instanceof TagNode) {
    			System.out.println(((TagNode)dom).start);
    			for (DomTree tag : ((TagNode)dom).children) {
    				print(tag);
    			}
    			System.out.println(((TagNode)dom).end);
    		} else {
    			System.out.println(((ContentNode)dom).content);
    		}		
    	}
    }
    
    // composite design pattern
    class DomTree {	
    }
    
    class ContentNode extends DomTree {
    	String content;
    	
    	@Override
    	public String toString() {
    		return content;
    	}	
    }
    
    class TagNode extends DomTree {
    	List<DomTree> children = new ArrayList<>();
    	String start;
    	String end;
    
    	public List<DomTree> getChildren() {
    		return children;
    	}
    
    	public void setChildren(List<DomTree> children) {
    		this.children = children;
    	}
    	
    	@Override
    	public String toString() {
    		return start + children.toString() + end;
    	}
    }
    
    /*
     *<Story>
    	  <id>1234</id>
    	  <Snaps>
    	      <Snap></Snap>
    	      <Snap></Snap>
    	      <Snap></Snap>
    	      <Snap></Snap>
    	  </Snaps>
      <Story>
    */

Log in to reply
 

Looks like your connection to LeetCode Discuss was lost, please wait while we try to reconnect.