Parseando tags com o mesmo nome como lista : DOM [RESOLVIDO]

Olá… eu estou fazendo um xml que representa um menu…

E queria escrever o xml assim…

<?xml version="1.0" encoding="UTF-8"?>
<mainmenu>
	<submenus>
		<menu name="Cadastro" type="menu">
			<submenus>
				<menu name="Cliente" type="menu">
					<submenus>
						<menu name="Cadastrar" type="item" />
						<menu name="Consultar" type="item" />
					</submenus>
				</menu>
				<menu name="Empresa" type="menu">
					<submenus>
						<menu name="Cadastrar" type="item" />
						<menu name="Consultar" type="item" />
					</submenus>
				</menu>
			</submenus>
		</menu>
		<menu name="Servicos" type="menu">
			<submenus>
				<menu name="Cotacao" type="menu">
					<submenus>
						<menu name="Cadastrar" type="item" />
						<menu name="Consultar" type="item" />
					</submenus>
				</menu>
				<menu name="Ordem de Coleta" type="menu">
					<submenus>
						<menu name="Cadastrar" type="item" />
						<menu name="Consultar" type="item" />
					</submenus>
				</menu>
			</submenus>
		</menu>
		<menu name="Sair" type="item" />
	</submenus>
</mainmenu>

Tentei parsea-lo assim:

DocumentBuilderFactory factory = DocumentBuilderFactoryImpl
				.newInstance();
		DocumentBuilder db = factory.newDocumentBuilder();
		Document doc = db.parse(file);

		JFrame frame = new JFrame();
		JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);

		Element elem = doc.getDocumentElement();
		NodeList nl = elem.getElementsByTagName("submenus");

		for (int i = 0; i < nl.getLength(); i++) {
			Element element = (Element) nl.item(i);
			String type = element.getAttribute("type");
			if (type.equals("menu")) {
				JMenu menu = new JMenu(element.getAttribute("name"));
				NodeList snl = element.getElementsByTagName("submenus");
				for (int j = 0; j < snl.getLength(); j++) {
					Element el = (Element) snl.item(j);
					JMenuItem menuItem = new JMenuItem(el.getAttribute("name"));
					menu.add(menuItem);
				}
				menuBar.add(menu);
			} else if (type.equals("item")) {
				JMenuItem menuItem = new JMenuItem(element.getAttribute("name"));
				menuBar.add(menuItem);
			}
		}
		frame.pack();
		frame.setVisible(true);

Mas ele pega todos as tags submenus e eu queria só as que tivessem dentro da tag mainmenu e as outras eu vou parseando de acordo com os menus.

Eu tentei usar o XStream…

Ele funciona… o problema é o que ele gera:

<br.mf.menu.MainMenu>
  <menus>
    <br.mf.menu.Menu>
      <name>Cadastro</name>
      <submenus>
        <br.mf.menu.Menu>
          <name>Cliente</name>
          <submenus>
            <br.mf.menu.Menu>
              <name>Cadastrar</name>
              <submenus/>
              <type>item</type>
            </br.mf.menu.Menu>
            <br.mf.menu.Menu>
              <name>Cadastrar</name>
              <submenus/>
              <type>item</type>
            </br.mf.menu.Menu>
          </submenus>
          <type>menu</type>
        </br.mf.menu.Menu>
        <br.mf.menu.Menu>
          <name>Empresa</name>
          <submenus>
            <br.mf.menu.Menu>
              <name>Cadastrar</name>
              <submenus/>
              <type>item</type>
            </br.mf.menu.Menu>
            <br.mf.menu.Menu reference="../br.mf.menu.Menu"/>
          </submenus>
          <type>menu</type>
        </br.mf.menu.Menu>
      </submenus>
      <type>menu</type>
    </br.mf.menu.Menu>
    <br.mf.menu.Menu>
      <name>Servicos</name>
      <submenus>
        <br.mf.menu.Menu>
          <name>Cotacao</name>
          <submenus>
            <br.mf.menu.Menu>
              <name>Cadastrar</name>
              <submenus/>
              <type>item</type>
            </br.mf.menu.Menu>
            <br.mf.menu.Menu>
              <name>Cadastrar</name>
              <submenus/>
              <type>item</type>
            </br.mf.menu.Menu>
          </submenus>
          <type>menu</type>
        </br.mf.menu.Menu>
        <br.mf.menu.Menu>
          <name>Ordem de Coleta</name>
          <submenus>
            <br.mf.menu.Menu>
              <name>Cadastrar</name>
              <submenus/>
              <type>item</type>
            </br.mf.menu.Menu>
            <br.mf.menu.Menu reference="../br.mf.menu.Menu"/>
          </submenus>
          <type>menu</type>
        </br.mf.menu.Menu>
      </submenus>
      <type>menu</type>
    </br.mf.menu.Menu>
    <br.mf.menu.Menu>
      <name>Sair</name>
      <submenus/>
      <type>item</type>
    </br.mf.menu.Menu>
  </menus>
</br.mf.menu.MainMenu>

O Usuario final vai escrever isso na mão e dessa forma não parece interessante… já trabalhei com xml e sei quanto é chato ficar fazendo isso.

Então… tem como eu parsear o XML que nem mostrei em cima?

da uma lida la no tutorial do xstream la ele fala sobre alias e tudo mais que vc precisa para deixar o xml igual!!!

No seu caso, em vez de “getElementsByTagName” (que pega todos os elementos e subelementos recursivamente, não só os do primeiro nível imediatamente abaixo) você precisa escrever uma rotina recursiva (porque sua estrutura de dados é recursiva) que pega simplesmente os elementos “children” do primeiro nível imediatamente abaixo.

beste tutorial vc tem a parte de alias e tb como colocar um atrubuto da classe como atributo da tag

http://xstream.codehaus.org/alias-tutorial.html

Aew… resolvi…

valeu thingol…

@nextuser
Olhei pouca coisa sobre o alias do XStream mas valeu…

Aqui o código que fiz:

	public void proccessMenuNodeList(NodeList nl, JMenuBar menubar) {
		for (int i = 0; i < nl.getLength(); i++) {
			proccessMenuNode(nl.item(i), menubar);
		}
	}

	public void proccessMenuNode(Node n, Container parent) {
		if(!n.getNodeName().equals("menu"))
			return;
		Element element = (Element) n;
		String type = element.getAttribute("type");
		String name = element.getAttribute("name");
		if (type.equals("menu")) {
			NodeList nl = element.getChildNodes();
			JMenu menu = new JMenu(name);

			for (int i = 0; i < nl.getLength(); i++)
				proccessMenuNode(nl.item(i), menu);

			parent.add(menu);
		} else if (type.equals("item")) {
			JMenuItem item = new JMenuItem(name);
			parent.add(item);
		}
	}

E para chamar:

	DocumentBuilderFactory factory = DocumentBuilderFactoryImpl
				.newInstance();
		DocumentBuilder db = factory.newDocumentBuilder();
		Document doc = db.parse(file);

		JFrame frame = new JFrame();
		JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);

		Element elem = doc.getDocumentElement();

		NodeList nl = elem.getChildNodes();
		
		proccessMenuNodeList(nl, menuBar);
		
		frame.pack();
		frame.setVisible(true);

Parabéns por usar a recursividade. Você fez exatamente o que eu estava pensando.

E para quem acha que recursividade é uma coisa inútil que se aprende na escola e depois você joga fora: prepare-se, porque uma hora você vai acabar usando. Quem leu a solução do Mark_Ameba descobriu que é bastante elegante e simples de compreender.

[quote=thingol]Parabéns por usar a recursividade. Você fez exatamente o que eu estava pensando.

E para quem acha que recursividade é uma coisa inútil que se aprende na escola e depois você joga fora: prepare-se, porque uma hora você vai acabar usando. Quem leu a solução do Mark_Ameba descobriu que é bastante elegante e simples de compreender.
[/quote]

ty

Só uma coisinha. Quando você faz um cast de Node para Element você tem de tomar um pouco de cuidado, porque se o usuário puser um “<!-- comment -->” nesse seu arquivo, seu programa vai explodir. Só faça uma verificaçãozinha bobinha para não ter problemas.

É eu percebi que tava dando uns erros… por isso coloquei a linha

if (!n.getNodeName().equals("menu"))
			return;