Eu gostaria de escrever um script que:
- Toma algum URL de RSS-Feed como entrada
- Baixe o feed
- Exclui todas as
<item> ...</item>
ocorrências em que atitle
tag não corresponde a alguma expressão regular.
O exemplo a seguir deve ilustrar isso. Digamos que temos um RSS Feed com esses três itens:
- Projeto Foo - Vamos começar!
- Algo totalmente diferente
- Outra atualização sobre o Projeto Foo
Quero manter apenas os itens que têm "Projeto Foo" em seu título.
Exemplo de arquivo de entrada:
<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0">
<channel>
<title>My glorious newsfeed</title>
<description>...</description>
<link>...</link>
<language>...</language>
<pubDate>...</pubDate>
<item>
<title>Project Foo - Let's get started!</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>
<item>
<title>Something else entirely</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>
<item>
<title>Another update on Project Foo</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>
</channel>
</rss>
Exemplo de arquivo de saída:
<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0">
<channel>
<title>My glorious newsfeed</title>
<description>...</description>
<link>...</link>
<language>...</language>
<pubDate>...</pubDate>
<item>
<title>Project Foo - Let's get started!</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>
<item>
<title>Another update on Project Foo</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>
</channel>
</rss>
Se possível, gostaria de ficar longe de coisas como python
e fazer isso com ferramentas de linha de comando. Mas eu sou um grande novato usando sed
etc. e preciso de ajuda :)
Aqui está o que eu tenho até agora:
cat sample-feed.xml \
| tr -d '\n' \
| sed $'s/\<item\>/\\\n\<item\>/g;s/\<\/channel\><\/rss\>/\\\n\<\/channel\><\/rss\>/g' \
| sed '/^\<item\>/ d'
Primeiro, excluo todas as novas linhas. Em seguida, adiciono novas linhas para trazer cada uma <item>...</item>
para sua própria linha. O comando final até agora exclui todas as linhas que começam com <item>
. Por
O resultado é um feed rss válido sem nenhum item:
<?xml version="1.0" encoding="iso-8859-1"?><rss version="2.0"><channel><title>My glorious newsfeed</title><description>...</description><link>...</link><language>...</language><pubDate>...</pubDate>
</channel></rss>
Para fazer isso funcionar com URLs em vez de arquivos locais, eu apenas substituiria cat sample-feed.xml
por curl -s <some url>
.
O que ainda falta é uma modificação no comando sed '/^\<item\>/ d'
que exclui apenas as linhas que começam com <item>
, mas não contêm "Projeto Foo".
Então, se você pudesse me ajudar a descobrir o que a última linha deveria dizer, eu ficaria muito feliz. Por outro lado, tenho certeza de que existe uma maneira mais elegante de fazer isso. Pelo que vi, sed
é bastante poderoso e deve ser possível fazer isso em um sed
comando.
Aguardo suas respostas :-)
Conforme sugerido nos comentários, tentei usar
xmlstarlet
para resolver isso e funciona bem. Aqui está o meu roteiroVamos supor que o conteúdo do feed esteja no arquivo
sample_rss.xml
. Esse conteúdo é alimentado emxml ed -d
, que exclui qualquer nota que corresponda à expressão XPath fornecida. A expressão XPath procura por qualquer um<item>
que não tenha um nó<title>
que contenha o texto"Project Foo"
.Isso parece funcionar bem e também estou muito feliz com o tempo de execução:
Cuidado com os namespaces
Se você quiser fazer isso funcionar com feeds rss ou atom adequados, você pode perceber que
feed
contém um atributo XML Namespace (xmlns
), assim como neste exemplo do YouTube:Então, o script acima não funcionará mais! Isso me causou muita dor de cabeça consertá-lo, mas aqui está como fazê-lo funcionar:
Mais sobre este problema de namespace aqui: http://xmlstar.sourceforge.net/doc/UG/ch05.html