HTML/XML - Obter texto de nós ancestrais

Olá, pessoal

Estou tentando obter uma tabela a partir de uma lista estruturada na forma de HTML. Basicamente, a minha ideia é obter o valor final (texto) dos últimos níveis de cada ramo da lista e uma coluna com a concatenação dos nós ancestrais.
Já tentei usar o xpath ancestor::, com xml2::xml_find_all(no_final, xpath = "//ancestor::span"), já tentei usar XML::xmlAncestors(). Mas não consigo obter uma lista com as hierarquias. Obter os nós finais não é problema, mas não consigo obter apenas os nós ancestrais para poder extrair o texto de cada nó ancestral e concatená-los. Além disso, o exemplo de solução mais próximo que encontrei na internet foi o relatado neste link: How to parse XML attributes with parent attribute into data frame in R - Stack Overflow , mas não funcionou para mim.

Vou deixar um exemplo ilustrativo abaixo, mas a lista do HTML é um pouco mais profunda e tem diferentes níveis. Contudo, creio se obtermos uma solução para o exemplo abaixo, daria para generalizar para qualquer tipo de lista, independentemente do seu nível.

Segue exemplo do arquivo html:

<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta id="dcsaassfapcmsdgsdgsddcgsd"></head><body><ul id="tree" class="filetree">
<li><span class="folder">TITULO 1</span>
	<ul>
		<li><span class="folder">SUB TITULO 1.1</span>
			<ul>
				<li><span class="file"><a class="linkMateria" data-id="646395" data-protocolo="590647" data-materia-id="641768"> #590647 - Dec20816</a></span>
				</li>
			</ul>
		</li>
		
		<li><span class="folder">SUB TITULO 1.2</span>
			<ul>
				<li><span class="folder">Portarias</span>
					<ul>
						<li><span class="file"><a class="linkMateria" data-id="646277" data-protocolo="590529" data-materia-id="641650"> #590529 - Integracao-202100600306</a></span>
						</li>
						<li><span class="file"><a class="linkMateria" data-id="646293" data-protocolo="590545" data-materia-id="641666"> #590545 - Integracao - 202100600305</a></span>
						</li>
					</ul>
				</li>
			</ul>
		</li>
		
		<li><span class="folder">SUB TITULO 1.3</span>
			<ul>
				<li><span class="folder">Subtitulo 1.3.1</span>
					<ul>
						<li><span class="folder">Portarias</span>
							<ul>
								<li><span class="file"><a class="linkMateria" data-id="646278" data-protocolo="590530" data-materia-id="641651"> #590530 - Integracao - 202103501172</a></span>
								</li>
								<li><span class="file"><a class="linkMateria" data-id="646281" data-protocolo="590533" data-materia-id="641654"> #590533 - Integracao - 202103501171</a></span>
								</li>
								<li><span class="file"><a class="linkMateria" data-id="646285" data-protocolo="590537" data-materia-id="641658"> #590537 - Integracao - 202103501170</a></span>
								</li>								
								
								<li><span class="file"><a class="linkMateria" data-id="646311" data-protocolo="590563" data-materia-id="641684"> #590563 - Integracao - 202103501160</a></span>
								</li>
								
							</ul>
						</li>
					</ul>
				</li>
			</ul>
		</li>
		<li><span class="folder">SUB TITULO 1.4</span>
			<ul>
				<li><span class="folder">Subtitulo 1.4.1</span>
					<ul>
						<li><span class="folder">Portarias</span>
							<ul>
								<li><span class="file"><a class="linkMateria" data-id="646274" data-protocolo="590526" data-materia-id="641647"> #590526 - Integracao - 202101000570</a></span>
								</li>
							</ul>
						</li>
					</ul>
				</li>
			</ul>
		</li>		
		
	</ul>
</li>

Imagem do HTML:
image

Segue exemplo do exemplo de tabela que quero obter:
image

Obrigado, desde já, se algum puder dar uma luz.

George,

Fiz um código completo só para ter um resultado final, mas a chave da resposta é que, na realidade, não existe nenhum ancestral span dos nós finais; todos os ancestrais relevantes são li com span dentro. O código que você precisava usar era ancestor::li/span.

html |>
  xml2::read_html() |>
  xml2::xml_find_all("//*[@class='file']") |>
  purrr::map(~list(
    no_final = xml2::xml_text(.x),
    nos_ancestrais = .x |>
      xml2::xml_find_all("./ancestor::li/span[@class='folder']") |>
      xml2::xml_text() |>
      stringr::str_c(collapse = ";")
  )) |>
  purrr::transpose() |>
  tibble::as_tibble() |>
  tidyr::unnest(dplyr::everything())
#> # A tibble: 8 × 2
#>   no_final                               nos_ancestrais                         
#>   <chr>                                  <chr>                                  
#> 1 " #590647 - Dec20816"                  TITULO 1;SUB TITULO 1.1                
#> 2 " #590529 - Integracao-202100600306"   TITULO 1;SUB TITULO 1.2;Portarias      
#> 3 " #590545 - Integracao - 202100600305" TITULO 1;SUB TITULO 1.2;Portarias      
#> 4 " #590530 - Integracao - 202103501172" TITULO 1;SUB TITULO 1.3;Subtitulo 1.3.…
#> 5 " #590533 - Integracao - 202103501171" TITULO 1;SUB TITULO 1.3;Subtitulo 1.3.…
#> 6 " #590537 - Integracao - 202103501170" TITULO 1;SUB TITULO 1.3;Subtitulo 1.3.…
#> 7 " #590563 - Integracao - 202103501160" TITULO 1;SUB TITULO 1.3;Subtitulo 1.3.…
#> 8 " #590526 - Integracao - 202101000570" TITULO 1;SUB TITULO 1.4;Subtitulo 1.4.…

Created on 2021-12-06 by the reprex package (v2.0.1)

1 curtida

Sensacional!!! Funcionou perfeitamente!!! Eu conheci essas sintaxes do xpath ancestor:: por agora. Nem sabia que existiam essas possibilidades, mas não achei muitos artigos na internet ensinando a usar. Além disso, o html que estou manipulando parece ter uma estrutura terrível de trabalhar.
Obrigado @clente !!!

1 curtida

Que bom que deu certo! Só para registrar, essa foi a fonte que eu usei: XPath Axes.