Avançar para a área de conteúdo

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Todas as informações enviadas são seguras.

  • Fechar [x]

Um plug-in do IBM Mashup Center para Converter de HTML para XML

Uma abordagem aprofundada sobre o desenvolvimento de um plug-in do IBM Mashup Center

Louis Mau, Solutions Architect, IBM
Louis Mau is part of the InfoSphere MashupHub development team. His current focus is to help customers build situational applications using the IBM Mashup Center. Prior to this role, he was the architect for DB2 Everyplace Sync Server, which helps synchronize data from enterprise databases onto a small foot print database running on mobile devices.

Resumo:  Aprenda como construir um plug-in para o IBM® O Mashup Center que pode converter HTML em XML, abrindo a porta para alguma extração de dados simples a partir de páginas HTML usando o Feed Mashup Editor.

Data:  18/Dez/2009
Nível:  Avançado
Atividade:  11402 visualizações
Comentários:  


Introdução

O IBM Mashup Center vem com geradores de feed que podem acessar e gerar feeds XML diretamente a partir de origens de dados corporativos. Ao mesmo tempo, devido à diversidade de armazenamentos de dados e de software, haverá origens de dados que não podem ser acessadas por estes geradores incorporados. Para permitir o aumento da capacidade do IBM Mashup Center, a capacidade de geração de feeds pode ser estendida através da inclusão de plug-ins.

Este artigo é uma sequência para o artigo " Estenda a abrangência de dados para IBM Mashup Center" e é baseado na V1.1 do software. Ele assume que você já está familiarizado com os fundamentos de escrita de plug-ins do IBM Mashup Center. Em particular, você deve saber como programar em Java™, JSP e JavaScript. O artigo mostra como desenvolver um plug-in para converter HTML em XML e usa este exemplo para ilustrar a escrita de um plug-in mais complexo. Como um benefício colateral, depois do HTML estar no formato XML, ele pode ser lido no Feed Mashup Editor, permitindo a extração de dados.


Ferramentas para conversão de HTML em XML

Precisamos de um pacote Java que converterá HTML em XML. Há uma série de pacotes Java. Este projeto usa JTidy, um conjunto Java do HTML Tidy do W3C. O HTML Tidy começou como um verificador de sintaxe HTML e uma impressora sofisticada. Como seu primo não-Java, o JTidy pode ser usado como uma ferramenta para limpeza malformada e HTML falho. Ele suporta, além disso, a geração de XML. Você encontrará um link na seção Recursos para fazer o download e instale o JTidy.

Você usará o Tidy.jar na pasta build. Para tornar o JAR autocontido, ele contém uma versão anterior das classes do DOM (Document Object Model) da W3C. Como as versões mais recentes das classes do DOM do W3C agora estão incluídas no JDK, as classes a partir do pacoteorg.w3c.dom devem ser removidas.


Configurando um Projeto Eclipse

Como descrito na Seção 6.1 da Referência da Interface de Programação de Aplicativos, Versão 1.0, a estrutura de geração de feeds automaticamente procura por arquivos ZIP contendo plug-ins de terceiros colocados na pasta especial <WebApplication>/WEB-INF/plugins. O archive ZIP deve ter a estrutura de pasta especificada a seguir:

  • /client/plugins/PLUGIN_DIR -- Contém arquivos para navegadores, como imagens, arquivos JavaScript e assim por diante.
  • /server/plugins/PLUGIN_DIR -- Contém os arquivos usados pelo plug-in para renderizar a si próprio (arquivos HTML, páginas JSP). Pastas adicionais para arquivos de plug-in podem estar incluídas.
  • /WEB-INF/classes -- Contém classes Java do plug-in. Isto pode ser uma hierarquia de pastas. As classes serão copiadas para <WebApplication>/WEB-INF/classes.
  • /WEB-INF/lib -- Contém arquivos JAR usados pelo plug-in (de terceiro).

Para simplificar a construção final e o empacotamento do plug-in, você pode desejar criar um projeto usando seu IDE favorito com a mesma estrutura de diretórios conforme exigido pelo archieve ZIP final. A Figura 1 mostra o layout do projeto Eclipse criado pelo autor.


Figura 1. Projeto Eclipse

Observe que o PLUGIN_DIR deve ser exclusivo e ter o mesmo nome do pacote do plug-in. Para este exemplo, eu usei o nome do pacote sample.mashupcenter.tidyhtml. Observe também que colocamos o Tidy.jar na pasta WEB-INF/lib e criamos uma pasta chamada lib_noship contendo dois JARs adicionais que são fornecidos pelo servidor Mashup Center durante o tempo de execução mas não estão disponíveis no ambiente de desenvolvimento. Estes JARs não deve estar incluídos no arquivo ZIP da implementação final. De fato, o carregamento do arquivo ZIP do plug-in poderia falhar se eles fossem incluídos por erro.


O arquivo plugin.xml

cada plug-in do Mashup Center possui duas operações principais: um editor para coletar os parâmetros de criação e um gerador para criar o feed. Feed normalmente se refere a um documento XML de acordo com a especificação RSS ou ATOM. Observe que neste caso, o XML gerado originará a partir do HTML e estará de acordo com a especificação RSS ou ATOM. A estrutura do plug-in descobre quais classes Java implementam as duas operações principais lendo o arquivo package.xml, que deve ser colocado na pasta server/plugins/PLUGIN_DIR. A Lista 1 mostra o arquivo package.xml para este plug-in.


Lista 1. Arquivo de pacote XML
<plugin>
  <name>Tidy Html</name>
  <author>L. Mau</author>
  <version>1.0</version>
  <category>departmental</category>
  <editor>Html2XmlEditorPlugin</editor>
  <generator>Html2XmlGeneratorPlugin</generator>
  <description>converte qualquer página HTML em XHTML</description>
  <icon16path>/plugins/sample.mashupcenter.tidyhtml/icons/btn16_hello.gif</
	icon16path>
  <icon32path>/plugins/sample.mashupcenter.tidyhtml/icons/btn32_hello.gif</
	icon32path>
  <icon64path>/plugins/sample.mashupcenter.tidyhtml/icons/btn64_hello.gif</
	icon64path>
  <objectType>feed</objectType>
</plugin>

É importante mencionar que os elementos nome, descrição e versão são para benefício do criador e não use a estrutura do plug-in do IBM Mashup Center. A estrutura do plug-in usa as propriedades plugin.uiname dentro do arquivo ui.properties como o nome do plug-in quando apresenta a lista das opções após os usuários selecionarem Novo Feed.

O arquivo ui.properties reside na pasta /server/plugins/PLUGIN_DIR/nls e é carregado usando a convenção de carregamento do pacote de recursos Java padrão. Para cada idioma suportado, coloque a cadeia traduzida para plugin.name em um arquivo de propriedades com o código do idioma anexado à "ui." Por exemplo, a versão japonesa do arquivo deve ser nomeada como ui_ja.properties.


Implementando o editor

O Html2XmlEditorPlugin estende BaseEditorPlugin, uma classe base que nos exige implementar o método renderEditor.


Lista 2. Classe Html2XmlEditorPlugin
package sample.mashupcenter.tidyhtml;

import : : : : :   // omitido da listagem

/**
 * Este plug-in usa o JTidy para converter de HTML para XML.
 */
public class Html2XmlEditorPlugin extends BaseEditorPlugin {

    private static final Log log = LogFactory.getLog(Html2XmlEditorPlugin.class);

    public  static final String I18N_RESFILE = Html2XmlConstants.PLUGIN_NAME
                                         + ".nls.tidyhtml";
    public  static final String HTTP_BASEURL = "plugins/"
                                         + Html2XmlConstants.PLUGIN_NAME +  "/";
    public  static final String RES_BASEURL  = "/" + HTTP_BASEURL;
    public  static final String HELPPATH     = HTTP_BASEURL + "help/tidyhtml.htm";

A primeira instrução na classe cria uma instância do log estático a partir do pacote de registro comum do Apache. Esta é a mesma estrutura de registro que a usada pela infraestrutura de geração de feeds. As mensagens de log serão interpostas por aquelas da estrutura de geração de feeds e serão gravadas no arquivo <WebApplication>/META-INF/logs/javamashuphub.log a seguir. Pelo padrão, somente mensagens do WARN e acima (por exemplo ERROR) serão gravadas no arquivo de log.

A próxima instrução é a constante da cadeia para um arquivo de recursos. Mesmo se não houver necessidade de traduzir todas as constantes da para diferentes idiomas, é uma boa prática de programação manter todas as cadeias de texto exibidas pela interface com o usuário em um arquivo de recursos separado. Observe que o arquivo tidyhtml.properties está colocado no mesmo diretório que o arquivo ui.properties descrito anteriormente.

As últimas poucas constantes da cadeia definem os caminhos para vários recursos necessários pelo plug-in. Observe que o local do tempo de execução destes recursos imitam a estrutura do arquivo ZIP do plug-in.


Método renderEditor

O método renderEditor usa dois parâmetros: RequestData e Entry. Este método é chamado pela estrutura quando os usuários selecionam criar um novo feed usando este plug-in, ou quando os usuários editam um feed existente, anteriormente criado por este plug-in. Como veremos, o método usar dois parâmetros de tipos RequestData e Entry. Os dois parâmetros são realmente comuns a todos os métodos chamados pela estrutura na resposta às ações do usuário. O RequestData contém informações enviadas a partir do navegador e Entry contém todas as informações mantidas pela estrutura para esta instância do feed.


Lista 3. Corpo do método renderEditor
public ViewBean renderEditor(RequestData rdata, Entry entry)
{
    ResourceBundle i18n = ResourceBundle.getBundle(I18N_RESFILE,rdata.getLocale());
    String pluginId = this.getId();

    Html2XmlUrlViewBean htViewBean = new Html2XmlUrlViewBean();
    htViewBean.setEntry(entry);
    htViewBean.setHtmlUrl( entry.getAttribute(Html2XmlUrlViewBean.PARAM_HTMLURL ) );
    htViewBean.setSnapshot( entry.getAttribute(Html2XmlUrlViewBean.PARAM_SNAPSHOT ) );

    FormViewBean form = new FormViewBean();
    form.setSuffix( htViewBean.getSuffix() );
    form.addComponent( htViewBean );
    form.setOnsubmit( PluginHelper.getClientMe(pluginId, entry.getObjectId()) +
            ".invokeServer('displayHtmlPage',"  +
            PluginHelper.getClientId(pluginId, entry.getObjectId()) +
            "_" + form.getSuffix() + ");");
    form.setEntry(entry);

    FrameViewBean frame = new FrameViewBean();
    frame.addComponent(form);
    frame.setLabel(entry.getTitle());
    frame.setTitle(i18n.getString("frame.urltitle"));
    frame.setEntry(entry);
    frame.setHelpPath( HELPPATH );
    return frame;
}

O método retorna uma instância de tipo ViewBean. ViewBean é similar ao Java Bean com getters e setters para propriedades de exibição. Sua principal finalidade é especificar o JSP usado pela estrutura de geração de feeds para criar HTML para o editor específico do plug-in. Como o método renderEditor não pode ser chamado para editar uma instância existente, ele recupera todos os dados salvos anteriormente para esta instância chamando o método Entry::getAttribute. Veremos posteriormente quando e como estes dados são salvos. O valor recuperado é então passado para o Html2XmlUrlViewBean para que o JSP associado possa exibir o valor anteriormente fornecido pelo usuário. Observe que o Html2XmlViewBean específico do plug-in não é retornado diretamente, mas em vez disso é quebrado dentro da instância FormViewBean através do método addComponent. O FormViewBean fornece a lógica JavaScript customizada para enviar as informações digitadas pelo usuário para o plug-in quando o botão Avançar na interface do editor do tipo assistente é clicado. Finalmente, o FormViewBean é então quebrado dentro de um FrameViewBean. Ele é o mais recente retornado.

Um última observação antes de movê-lo. Chamamos o método setOnsubmit para fornecer a parte do código JavaScript para executar quando o botão Avançar for clicado. O código JavaScript chama a função invokeServer do hub.managers.InvokePlugin descrita na Seção 6.3.2 da Referência da Interface de Programação de Aplicativos. O primeiro parâmetro especifica o método displayHtmlPage nesta classe que será usada para servir a próxima página do editor.


Html2XmlUrlViewBean e sue arquivo JSP associado

Já descrevemos brevemente o Html2XmlUrlViewBean na seção anterior. A Lista 4 mostra parte da definição de classe:


Lista 4. Html2XmlUrlViewBean
public class Html2XmlUrlViewBean extends ViewBean
{
  public static final String PARAM_HTMLURL     = "htmlurl";
  public static final String PARAM_SNAPSHOT    = "snapshot";
	
  private String  htmlUrl;
  private String  snapshot;

  public Html2XmlUrlViewBean()
 {
    this.setI18NProperties( Html2XmlConstants.PLUGIN_NAME + ".nls.tidyhtml");
 }

  /* (non-Javadoc)
   * @see com.ibm.mashuphub.model.ViewBean#getJSPPath()
   */
  @Override
  public String getJSPPath() {
    return "/server/plugins/" + Html2XmlConstants.PLUGIN_NAME + "/tidyhtmlUrl.jsp";
 }

 public String getSuffix() {
    return "tidyhtmlUrl";
 }

O método getJSPPath será chamado pelo FormViewBean quando ele tentar gerar o formulário HTML para reunião destes parâmetros específicos do plug-in. O método getSuffix deve retornar uma cadeia exclusiva entre os diversos ViewBeans deste plug-in. Antes de procurar no arquivo JSP associado, ele ajuda primeiro a procurar no formulário HTML renderizado:


Figura 2. Primeira página do editor InfoSphere MashupHug

Observe que o formulário possui dois elementos de entrada:

  • Um campo de texto para coleta da URL para HTML que o usuário deseja converter para XML e
  • Uma caixa de opção para indicar que iremos salvar o XML gerado na primeira chamada e simplesmente retornará o XML nos pedidos de geração de feeds subsequentes. Isto é adequado quando a página HTML for estática e raramente muda.

Agora que vimos o que deve ser gerado, é muito mais fácil entender o arquivo JSP.


Lista 5. tidyhtmlUrl.jsp
<%@page import="sample.mashupcenter.tidyhtml.Html2XmlUrlViewBean"%>
<%
    Html2XmlUrlViewBean htViewBean = new Html2XmlUrlViewBean();
    htViewBean = (Html2XmlUrlViewBean) htViewBean.getViewBeanFromRequest(request);
ResourceBundle i18n = ResourceBundle.getBundle(htViewBean.getI18NProperties(),
                                               request.getLocale());

    String objectId = htViewBean.getEntry().getObjectId();
String id = com.ibm.mashuphub.helper.PluginHelper.getClientId(
                                            htViewBean.getPluginId(), objectId);
%>

<br/>

<label for='htmlurl'><%=i18n.getString("form.htmlurl.label") %></label>
<div  class="rightCol">
   <input type='text'
          id='<%=id%>_htmlurl'
          name='<%= Html2XmlUrlViewBean.PARAM_HTMLURL %>'
          value='<%= htViewBean.getHtmlUrl() %>'
          maxlength='256' style='width=600px;' />
</div>

<div   class="rightCol">
   <input type='checkbox'
          id='<%=id%>_snapshot'
          name='<%= Html2XmlUrlViewBean.PARAM_SNAPSHOT %>'
          value='y'
          <%= "y".equals(htViewBean.getSnapshot()) ? "verificado" : "" %>  />
   <%= i18n.getString("form.snapshot.label") %>
</div>

Se for ignorada a instrução de importação, a finalidade das duas primeiras instruções é recuperar o ViewBean associado ao JSP. É um pouco diferente da forma como os JSPs tipicamente recuperam seus Java beans associados, que é a partir do objeto do pedido. Correspondente aos elementos de entrada de formulário, há dois elementos de entrada HTML do tipo texto e uma caixa de opção, respectivamente. Observe que usamos as constantes PARAM_HTMLURL e PARAM_SNAPSHOT a partir da classe Html2XmlUrlViewBean para nomear os dois elementos de entrada. Estes nomes aparecerão como nomes na cadeia de consulta da URL enviada quando o botão Avançar é clicado. Usar as constantes da cadeia é a melhor forma de assegurar que elas correspondam exatamente ao que O servidor espera. Finalmente, inicializamos estes elementos de entrada usando o valor anterior recuperado pelo método renderEditor.


Método DisplayHtmlPage

Eu mencionei anteriormente nesta seção que o método displayHtmlPage na classe Html2XMLEditorPlugin será usado para servir a próxima página do editor. O método displayHtmlPage não é herdado da classe base BaseEditorPlugin e usa dois parâmetros de tipo RequestData e Entry. Um EditorPlugin pode apresentar qualquer quantidade de métodos públicos com a mesma assinatura. Todos estes métodos podem ser chamados pelo cliente executando no navegador através de uma chamada AJAX.


Lista 6. Método displayHtmlPage
public  ViewBean  displayHtmlPage(RequestData rdata, Entry entry)
{
    ResourceBundle i18n = ResourceBundle.getBundle(I18N_RESFILE,rdata.getLocale());
    String pluginId = this.getId();

    // do not use "url" since the latter got intercepted in RequestData.init();
    String  sHtmlUrl  = rdata.getParameter( Html2XmlUrlViewBean.PARAM_HTMLURL );
    String  snapshot  = rdata.getParameter( Html2XmlUrlViewBean.PARAM_SNAPSHOT );
    log.debug("snapshot,sHtml=" + snapshot + "," + sHtmlUrl );

    Html2XmlContentViewBean htViewBean = new Html2XmlContentViewBean();
    htViewBean.setEntry(entry);
    htViewBean.setHtmlUrl( sHtmlUrl );
    htViewBean.setSnapshot( snapshot );

    FormViewBean form = new FormViewBean();
    form.setSuffix( htViewBean.getSuffix() );
    form.addComponent( htViewBean );
form.setOnsubmit(PluginHelper.getClientMe(pluginId,
                                          entry.getObjectId())+".submit();");
    form.setEntry(entry); // must be set, used to init JS plugin object

    FrameViewBean frame = new FrameViewBean();
    frame.addComponent(form);
    frame.setLabel(entry.getTitle());
    frame.setTitle(i18n.getString("frame.tabtitle"));
    frame.setEntry(entry);
    frame.setHelpPath( HELPPATH );

    JSONAJAXResponseViewBean ajaxViewBean = new JSONAJAXResponseViewBean();
    ajaxViewBean.setMethod(JSONAJAXResponseViewBean.METHOD_SHOW_EDITOR);
    ajaxViewBean.setCode( JSONAJAXResponseViewBean.PAGE_CONTENT );
    ajaxViewBean.addComponent(frame);
    return ajaxViewBean;
}

O propósito deste método é gerar uma segunda página do editor para os usuários verificarem o conteúdo do HTML recuperado. O correto é um tipo de retorno ViewBean. A lógica dentro do método displayHtmlPage é similar ao método renderEditor discutido anteriormente com três diferenças perceptíveis:

  • Em vez de recuperar valores de configuração anteriormente digitados a partir da instância Entry, recuperamos o que o usuário digitou durante esta sessão de edição chamando o método getParameter do RequestData. Estes parâmetros correspondem aos elementos de entrada no formulário JSP enviado através de uma chamada AJAX para o servidor.
  • Cada página exige um ViewBean diferente. Este método instancia uma instância de Html2XmlContentViewBean. Como antes, ele deve ser quebrado dentro de um cadeia FormViewBean, FrameViewBean. Além disso, precisamos quebrar ainda mais o FrameViewBean em uma instância JSONAJAXResponseViewBean. O mais recente acontecido automaticamente no método renderEditor mas precisa ser explicitamente feito aqui.
  • Como forneceremos nosso próprio JavaScript, mostramos uma pequena variação no JavaScript passado no método setOnsubmit. Em vez de chamar diretamente invokeServer, chamaremos o método submitno JavaScript associado.

Um detalhe adicional importante é a chamada para a instância do criador de logs estático para registrar parâmetros específicos do usuário para ajudar na determinação de problemas.


Html2XmlContentViewBean e o JSP associado

O Html2XmlContentViewBean é muito simples e basicamente retorna apenas um caminho JSP diferente e o sufixo do Html2XmlUrlViewBean que procuramos anteriormente. O leitor pode examiná-lo através do pacote anexado e não insistiremos sobre ele. A página do editor a ser gerada também é simples, consistindo de uma área para exibir o HTML recuperado. A captura de tela a seguir mostra um canto da área de exibição:


Figura 3. Visualização da página de conteúdo HTML

Examinamos em seguida o arquivo JSP associado tidyhtmlContent.jsp. Para gerar a área de exibição, você pode ver que o JSP associado simplesmente inclui um único elemento div na parte inferior do arquivo JSP. Como usaremos o atributo do id posteriormente, este é um bom lugar para discutir sua construção.

O atributo do id deve ser exclusivo entre todos elementos HTML dentro de uma janela do navegador. Usando o id, a API fornecida pelo navegador pode recuperar os elementos HTML como objetos DOM JavaScript, permitindo a manipulação dinâmica. Como um usuário tem múltiplas instâncias de um editor de plug-ins aberta ao mesmo tempo, os elementos HTML no modelo JSP serão instanciados múltiplas vezes. Para assegurar que os IDs desses elementos sejam exclusivos, chamamos o método getClientId do PluginHelper para recuperar o ID de instância de feed exclusivo e anexá-lo ao ID.


Lista 7. tidyhtmlContent.jsp
<%@page import="sample.mashupcenter.tidyhtml.Html2XmlContentViewBean"%>
<%
    Html2XmlContentViewBean htViewBean = new Html2XmlContentViewBean();
    htViewBean = (Html2XmlContentViewBean) htViewBean.getViewBeanFromRequest(request);
ResourceBundle i18n = ResourceBundle.getBundle(htViewBean.getI18NProperties(),
                                               request.getLocale());

    String objectId = htViewBean.getEntry().getObjectId();
String id = com.ibm.mashuphub.helper.PluginHelper.getClientId(
                                             htViewBean.getPluginId(), objectId);
String me = com.ibm.mashuphub.helper.PluginHelper.getClientMe(
                                             htViewBean.getPluginId(), objectId);

    String   snapshot    = "\"" + htViewBean.getSnapshot() + "\"";
    String   htmlUrl     = htViewBean.getHtmlUrl();
    htmlUrl     = ( htmlUrl == null ?  "\"\""   :  "\"" + htmlUrl + "\"" ); 
%>
<script type="text/javascript">

    dojo.registerModulePath("plugins.tidyhtml" ,
                 "../../../../client/plugins/sample.mashupcenter.tidyhtml/script");
    dojo.require("plugins.tidyhtml.PreviewHtml");

    new plugins.tidyhtml.PreviewHtml(
               <%= me %>.plugin_id,
               <%= me %>.entry_id,
               <%= me %>.workflow);

    <%=me%>.init( <%= htmlUrl %> , <%= snapshot %> );
    <%=me%>.onLoadEditor();

</script>

<div id='<%=id%>_htmlContent' style='width:100%;
     overflow:auto; border: 2px  solid #000000;'>
</div>

Um novo aspecto deste JSP é a inclusão de JavaScript customizado a ser executado no lado do cliente. A estrutura de geração de feeds do IBM Mashup Center usa o pacote Dojo AJAX. Consulte a seção Recursos para o link para a documentação do Dojo. Estaremos usando o pacote Dojo AJAX em nosso JavaScript customizado. A maior parte do JavaScript customizado reside em uma classe Dojo chamada "plugins.tidyhtml.PreviewHtml".

Para usá-lo, precisamos importá-lo usando uma chamada de função dojo.require. A chamada de função registerModulePath do Dojo é usada para dizer ao Dojo como localizar as classes a partir do "módulo" plugins.tidyhtml. Observe que o caminho especificado seja relativo ao caminho onde o pacote Dojo está localizado e, dessa forma, exige a referência de retrocesso "../../../..". A lógica de inicialização acima é gerada de forma sequencial dentro de uma tag de script. Além disso, o JavaScript sequencial cria uma instância da classe PreviewHtml e chama seus métodos init e onLoadEditor. A próxima seção examina em muitos detalhes da classe PreviewHtml.


classe Dojo PreviewHtml

A classe Dojo PreviewHtml herda da classe hub.managers.InvokePlugin que é parte da estrutura de geração de feeds do lado do cliente. A classe InvokePlugin é descrita ainda mais na seção 6.3.2 da Referência da Interface de Programação de Aplicativos, Versão 1.0. Os métodos de importância na classe Dojo PreviewHtml são onLoadEditor e populateContent.


Lista 8. Classe Dojo PreviewHtml
onLoadEditor: function()
{
    this.id = this.getEditorId();
    this.htmlContentNode = dojo.byId( this.id + '_htmlContent' );

    this.populateContent();
},

populateContent: function( )
{
    console.log( "populateContent chamado" );

    var baseUrl = hub.urls.getAjaxUrl( this.plugin_id,this.entry_id, 'getHtmlContent');
    var htmlurl = baseUrl + "?htmlurl="   + escape( this.htmlUrl   );
    if ( this.htmlContentInternalNode )
        this.htmlContentNode.removeChild( this.htmlContentInternalNode );
    this.htmlContentInternalNode = document.createElement( 'iframe' );
    this.htmlContentInternalNode.setAttribute( "src", htmlurl ); 
    this.htmlContentInternalNode.setAttribute( "width", "100%" );
    this.htmlContentInternalNode.setAttribute( "height", "400px" );  
    this.htmlContentNode.appendChild( this.htmlContentInternalNode );
},

A função populateContent é chamada de onLoadEditor durante o tempo de carregamento da página. Ela dinamicamente cria um iframe para exibir o HTML recuperado inicializando o efeito de todas as folhas de estilo incluídas e scripts evitando que eles afetem a aparência de outras páginas. O iframe dinamicamente criado é anexado ao div estático criado pelo JSP. Para recuperar o nó DOM correspondente à área de exibição, usamos o ID exclusivo do elemento div gerado pela anexação do ID de instância de feed exclusivo a um sufixo comum.

No lado do servidor, usamos um método na classe PluginHelper para obter o ID de instância de feed exclusivo. No lado do navegador, chamamos a função getEditorId do pai da classe Dojo PreviewHtml como, por exemplo, hub.managers.InvokePlugin. Para recuperar o conteúdo HTML, iremos tirar vantagem do atributo "src" do Iframe. O iframe será automaticamente recuperado e exibe o conteúdo apontado pelo atributo src durante a inicialização. Configuraremos o atributo src para chamar o método getHtmlContent do plug-in do editor. Observe a forma como criamos a URL chamando a função getAjaxUrl e anexando o resultado para a cadeia "getHtmlContent".


Método AJAX para recuperar HTML

Eu mencionei em uma seção anterior que todos os métodos públicos com RequestData e Entry como parâmetros podem ser chamados usando uma chamada AJAX. Em particular, o método getHtmlContent pode ser chamado pela classe Dojo PreviewHtml para retornar o HTML da URL fornecida pelo usuário. Como a recuperação de HTML real é comum para a geração de feeds e será abordada posteriormente, eu não fornecerei nenhum fragmento de código aqui. A única coisa que eu quero apontar é o tipo de retorno do método. No exemplo anterior, o método AJAX displayHtmlPage retorna um ViewBean. Os métodos AJAX em geral podem retornar qualquer objeto e seu valor toString será retornado. Consulte a seção 6.3.2 de Referência da Interface de Programação de Aplicativos, Versão 1.0.


Nosso último método do editor: saveFeedEntry

saveFeedEntry é outro método público de Html2XmlEditorPlugin chamado através do AJAX para manipular a etapa final no processo de edição, salvando o que o usuário digitou. Ele é simular aos métodos save em outros plug-ins. O que há de novo na manipulação de "recursos". Os recursos diferem de atributos em tamanho e tipo. Os recursos podem ser binários e podem ter até um gigabyte de tamanho. Em contraste, os atributos são limitados a cadeias de tamanho 10 MB. O tamanho limite para o atributo deve ser suficiente para o conteúdo, mas para fins ilustrativos, salvaremos o conteúdo HTML como um recurso. Quando a opção de captura instantânea está marcada, o gerador somente irá recuperar o conteúdo HTML a partir da URL especificada uma vez. O conteúdo HTML é então convertido para XML e salvo. Todos os pedidos de geração de feeds subsequentes serão satisfeitos a partir do XML salvo. Para tratar o caso em que o usuário desejar fazer outra captura instantânea porque o site pode ter mudado, gostaríamos de excluir a cópia salva sempre que o feed for editado. O fragmento de código mostra como isto é feito em um processo de duas etapas: recupere o recurso por nome, seguido pela chamada do método deleteResource no objeto retornado.


Lista 9. Método saveFeedEntry
try {
    entry.generateURL(rdata.getBaseUrl(), this.getId() );
    entry.addAttribute(Html2XmlUrlViewBean.PARAM_HTMLURL, sHtmlUrl , this.getId() );
    entry.addAttribute(Html2XmlUrlViewBean.PARAM_SNAPSHOT , snapshot , this.getId() );
    // depois de cada edição, limpe todas as capturas instantâneas armazenadas em cache
    Resource  oldRes = entry.getResource( Html2XmlConstants.CACHED_XHTML );
    if ( oldRes != null )
        oldRes.deleteResource();
    } catch (HubException ex) {
        log.error("Erro incluindo atributo de entrada.",ex);
}

Finalmente concluímos com o Editor e no Gerador.


GeneratorPlugin

A classe Html2XmlGeneratorPlugin estende o BaseGeneratorPlugin e deve implementar o método abstrato generateFeed. Não deveria ser surpresa que os parâmetros de entrada de tipo RequestData e Entry são idênticos ao que está sendo passado nos métodos EditorPlugin chamados pela estrutura de geração de feeds. Para gerar o feed, alguém deve primeiro recuperar os atributos contendo as informações de configuração salvas durante o processo de edição. Isto é feito através da chamada do método getAttribute a partir de Entry.


Lista 10. Método generateFeed
public FeedContent generateFeed(RequestData rdata, Entry entry) {
    String  sHtmlUrl  = entry.getAttribute(Html2XmlUrlViewBean.PARAM_HTMLURL );
    String  snapshot  = entry.getAttribute(Html2XmlUrlViewBean.PARAM_SNAPSHOT );

Como este plug-in não suporta a parametrização, não precisamos recuperar os parâmetros fornecidos pelo tempo de execução. Nós retornaremos o conteúdo XML salvo ou recuperaremos o conteúdo HTML e converteremos para XML usando JTidy. A lógica ilustra como os recursos são criados e é muito direta.


Lista 11. Corpo do generateFeed
String result = "O HTML pode ter mudado.  Tabela não localizada.";

Resource  oldRes = entry.getResource( Html2XmlConstants.CACHED_XHTML );
if ( "y".equals( snapshot ) &&  oldRes != null  ) {
   log.warn( "retornando armazenado em cache, captura instantânea=" + snapshot );
   return new FeedContent(oldRes.loadResource(), entry.getLifeTime());
}
            
String sHtml = getXhtml( sHtmlUrl );
if ( sHtml.length() > 0 ) {
    result = sHtml;
    if ( "y".equals( snapshot ) ) {
        try {
            Resource prepared = new Resource();
            prepared.setObjectid( entry.getObjectId() );
            prepared.setMimetype( "text/xml; charset=utf-8" );
            prepared.setFilename( Html2XmlConstants.CACHED_XHTML );
            prepared.uploadResource( sHtml.getBytes( "utf-8" ) );
       } catch (HubException e) {
            log.error(e);
       }
   }
}
return new FeedContent( result.getBytes( "utf-8" ), entry.getLifeTime());

Detalhes adicionais sobre como a entrada HTML que é convertida em XML pode ser localizada nos arquivos de origem Java. Eu apenas mencionarei dois pontos principais. Para tornar a saída XML utilizável pelo editor mashup de feeds, excluímos todas as declarações DOCTYPE. Além disso, a lógica de geração faz a suposição simplificada de que a entrada HTML está em UTF-8 e precisa ser melhorada para suportar outras linguagens.


Implementação

O projeto Eclipse completo com todos os arquivos de origem está disponível como um arquivo zip na área de download. Além disso, para facilitar tentar o plug-in, o arquivo zip do plug-in (sample.mashupcenter.tidyhtml.zip) também é fornecido. Para instalar o plug-in, execute as seguintes etapas:

  1. Faça download do Tidy.jar a partir do link na seção de recursos.
  2. Depois da remoção dos arquivos de classe do pacote org.w3c.dom, inclua o Tidy.jar no arquivo zip do plug-in no diretório WEB-INF/lib.
  3. Coloque o arquivo zip do plug-in no diretório <WebApplication>/WEB-INF/plugins.
  4. Pare e reinicie o servidor.

Conclusão

Já abordamos a construção de um plug-in mais complicado envolvendo múltiplas páginas do editor, JavaScript customizado e salvando os recursos. Você agora tem o básico para começar a estender as capacidades de geração de feeds do IBM Mashup Center. Um artigo subsequente discutirá tópicos mais avançados como segurança e parametrização.



Download

DescriçãoNomeTamanhoMétodo de download
Samples for this articleDownload.zip325KBHTTP

Informações sobre métodos de download


Recursos

Aprender

Obter produtos e tecnologias

Discutir

Sobre o autor

Louis Mau is part of the InfoSphere MashupHub development team. His current focus is to help customers build situational applications using the IBM Mashup Center. Prior to this role, he was the architect for DB2 Everyplace Sync Server, which helps synchronize data from enterprise databases onto a small foot print database running on mobile devices.

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Information Management, Lotus
ArticleID=457596
ArticleTitle=Um plug-in do IBM Mashup Center para Converter de HTML para XML
publish-date=12182009

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).