Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

An IBM Mashup Center plug-in to perform XSLT transforms

Introducing the Mashup Center v2.0 plug-in API

Louis Mau (louismau@us.ibm.com), Solution 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.

Summary:  Learn how to build an XSLT plug-in for Version 2 of the IBM® Mashup Center that takes advantage of the built-in support for Basic and Form-based authentication.

Date:  10 Dec 2009
Level:  Intermediate PDF:  A4 and Letter (176KB | 16 pages)Get Adobe® Reader®
Also available in:   Spanish

Activity:  14964 views
Comments:  

Introduction

IBM Mashup Center comes with a data mashup editor that you can use to combine and transform XML from multiple sources. The data mashup editor is easy to use, but in some scenarios you may find that it is more efficient to use XSLT to perform your XML transforms. So that you can learn how to get the benefit from both types of transforms, this article shows you how to build an IBM Mashup Center plug-in that can perform XSLT transformations.

"Extend the reach of data for IBM Mashup Center" and "An IBM Mashup Center plug-in to convert HTML to XML" are two earlier developerWorks articles that describe how to develop plug-ins to extend the capabilities of the IBM Mashup Center (see the Resources section for links). Those articles are based on Version 1 of the Mashup Center. The emphasis of this article is on the new capabilities in Version 2 of the plug-in API, such as Basic and Form-based authentication support. It only covers the areas where there are significant differences between Version 1 and Version 2 of the plug-in API.

This article assumes that you are already familiar with the basics of writing an IBM Mashup Center plug-in. In particular, you should know how to program in Java™, JSP, JavaScript, and XSLT.

A quick summary of the v2.0 plug-in API changes

Different plug-ins might require different versions of the same Java package. To provide the necessary isolation, starting in Version 2, classes for each plug-in are loaded using separate class loaders. Classes and plug-in specific jars are kept within the plug-in specific folder and are not copied to a common location as in Version 1. Interaction with the framework is now done mostly via interfaces rather than concrete classes. For example, the Version 1 renderEditor method used to take two concrete classes: RequestData and Entry as parameters. But in v2.0, class instances are changed to interfaces, as shown in Listing 1.


Listing 1. Use of interface as parameter

    // v1.1  public ViewBean renderEditor(RequestData rdata, Entry entry)
    public Object renderEditor(IEditorContext context)

The above changes do not have a significant effect on plug-in implementation. Where the v2.0 changes are most noticeable is in the plug-in JSP implementation. Since JSPs are loaded by the Web Container's JSP classloader, they cannot access plug-in specific (ViewBean) classes. Rather than using attribute specific getters, the v2.0 plug-in JSP needs to use generic name / value pairs to retrieve attributes. This is demonstrated in a later section.


Setting up an Eclipse project

As described in Section 6.1 of the Application Programming Interface Reference, Version 2.0 (see Resources for link), during startup, the server searches for ZIP files containing third party plug-ins that have been placed in the special <WebApplication>/WEB-INF/plugins folder. The ZIP archive must have the following folder structure:

  • /client/plugins/PLUGIN_DIR — Contains files for browsers, for example, images and JavaScript files.
  • /server/plugins/PLUGIN_DIR — Contains the plug-in manifest and files used by the plug-in to render itself (JSP pages).
  • /server/plugins/PLUGIN_DIR/classes — Contains the plug-in Java classes. This can be a hierarchy of folders.
  • /server/plugins/PLUGIN_DIR/lib — Contains JAR files used by the plug-in (third-party).

If you are familiar with developing v1.1 plug-ins, you may notice that the classes and lib folders are no longer placed under the WEB-INF folder. To simplify the final build and packaging of the plug-in, use your favorite IDE to create a project that has the same directory structure that is required by the final ZIP archive. Figure 1 shows the layout of a sample Eclipse project.


Figure 1. Eclipse project
Screen shot of the hierarchical structure of a sample Eclipse project following the ZIP file structure described above.

You can find the complete sample Eclipse project in the Download section. The example, uses the package name sample.mashupcenter.xslt for PLUGIN_DIR. It also contains an extra folder named lib_noship to hold the Version 2 IBM Mashup Center mhubapi.jar file that you need during development. You have to copy the mhubapi.jar file from your server's <installationDir>\Hub\installedApps\Mashup Hub.ear\mashuphub-enterprise.war\client\api folder. You only need this file during development; you should remove it from the final deployment-ready ZIP file.

Listing 2 shows the contents of the file named plugin.xml that is in the server/plugins/PLUGIN_DIR folder.


Listing 2. Package XML file
<?mhub version="2.0"?>
<plugin>
  <name>XSLT Transform</name>
  <description>Apply XSLT to transform XML</description>
  <author>IBM</author>
  <version>2.0</version>
  
  <extension id="sample.mashupcenter.xslt.transformeditor" 
             name="XSLT Transform Editor"
             point="com.ibm.mashuphub.core.extension.IEditor">
      <editor class="sample.mashupcenter.xslt.TransformEditorPlugin" 
              type="xslt" 
              category="departmental" 
              icon="/plugins/sample.mashupcenter.xslt/icons/btn16_hello.gif"
              name="%editor.name"
              description="%editor.description" /> 
  </extension>
  
  <extension id="sample.mashupcenter.xslt.transformgenerator" 
             name="XSLT Transform Generator"
             point="com.ibm.mashuphub.core.extension.IGenerator">
      <generator class="sample.mashupcenter.xslt.TransformGeneratorPlugin" 
                 type="xslt" />
  </extension>
</plugin>

Besides providing the basic plug-in information, the plugin.xml file contains names of classes that implement the Editor and Generator component. By default, the plug-in generates feeds and the name of the Editor is presented in a list when users select Create and then New Feed, as shown in Figure 2. Notice also that the Editor name appears under departmental, which is the category specified in the plug-in.xml file.


Figure 2. Feed plug-in selection listbox
Screenshot of the Mashup Center feed plug-in selection listbox with the new XSLT Transform selected.

To allow for internationalization, you should specify variables for the the name and description parameters. For example, in the plugin.xml example shown in Listing 2, %editor.name and %editor.description are variables. Their values are specified in a file named plugin.properties that resides in the same directory as plugin.xml. The plugin.properties file is loaded by the framework using the standard Java resource bundle loading convention. For each supported language, place the translated strings in a properties file with the locale appended to "plugin". For example, the Japanese version of the file should be named plugin_ja.properties.


Implementing the editor

As specified in the plugin.xml file, the TransformEditorPlugin class provides the plug-in editing function. Its implementation extends BaseEditor, a base class that requires implementation of the renderEditor method. The renderEditor method is called by the framework when users make the selection to create a new feed using this plug-in, or when users edit an existing feed previously created by this plug-in.


Listing 3. TransformEditorPlugin class
public class TransformEditorPlugin extends BaseEditor {

    @Override
    public Object renderEditor(IEditorContext context)
    {
        ResourceBundle i18n =
          ResourceBundle.getBundle(TransformConstants.I18N_RESFILE, context.getLocale());

        IEntry entry    = context.currentEntry();
        ILog  log = context.getLog();
        IRequestContext request = context.getRequestContext();

The renderEditor method in Version 2 takes a single parameter: IEditorContext. The parameter is common to all methods invoked by the framework in response to user editing actions. Recall the earlier discussion on using interfaces versus concrete classes. From the context, you get the IRequestContext interface containing information sent from the browser, and IEntry containing all the information maintained by the framework for this feed instance. The usage of these interfaces is similar to the usage of RequestData and Entry classes in Version 1, so this article does not provide any further information on this topic. If you would like more details though, you can refer to the two Version 1 articles mentioned earlier and linked to in the Resources section. You can find the Javadoc for the plug-in API on your IBM Mashup Center installation by going to this URL: http://<yourserver>/mashuphub/client/doc/javadoc/index.html.

Note also that the logging instance is now passed in and accessible through the IEditorContext parameter. Log messages are interleaved with those from the feed generation framework and are written to the following file: <WebApplication>/META-INF/logs/javamashuphub.log. By default, only messages with a severity of WARN and above (for example ERROR) are written to the log file.

Listing 4 shows the body of the renderEditor method.


Listing 4. renderEditor method body
    BasicEditorViewBean htViewBean = 
        new BasicEditorViewBean( TransformConstants.JSPPATH_TRANSFORM );
    htViewBean.setEntry(entry);
    htViewBean.setI18NProperties( TransformConstants.I18N_RESFILE );
    String  s = entry.getAttribute(TransformConstants.PARAM_XSLT );
    htViewBean.addAttribute( TransformConstants.PARAM_XSLT , escapeXml( s ) );
    IParameter  param = entry.getParameter( TransformConstants.PARAM_XMLURL );
    if ( param != null ) {
        htViewBean.addAttribute( TransformConstants.PARAM_XMLURL
                               , param.getDefaultValue() );
    }

    AuthHelper helper = AuthHelper.restoreFromEntry(context
                                                   , AuthConstants.AUTH_METHOD_BASIC
                                                   , null );
    ViewBean authViewBean = helper.getViewBean(context);

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

The renderEditor method returns an instance of the type ViewBean. The main purpose of the ViewBean is to specify the JSP used by the feed generation framework to create an HTML fragment for the plug-in specific editor. In Version 2, JSPs are loaded by the Web Container's JSP classloader and cannot access plug-in specific classes, such as a ViewBean. So instead of creating a plug-in specific ViewBean class, the sample above uses the generic BasicEditorViewBean class provided by the framework. The path to the plug-in specific JSP is passed in through the constructor. Plug-in specific parameters are passed to the BasicEditorViewBean instance through the generic addAttribute method rather than using parameter specific getters and setters. These plug-in specific parameters are used to pre-populate the editing form with values the user entered in earlier edit sessions.

As explained in one of the earlier articles, the plug-in specific ViewBean is not returned to the framework directly. Instead, it is added to the FormViewBean. The latter contains logic to interact with the framework and provide a wizard-like multi-step editing experience. The difference is that this example adds two ViewBeans to the FormViewBean. The FormViewBean can piece together multiple HTML fragments generated by JSPs and associated with multiple ViewBeans.

Figure 3 shows the form that is rendered from the two ViewBeans.


Figure 3. XSLT plug-in editor
Screenshot of a form with two required fields (XSLT and Test URL) and a check box that specifies if authentication is required.

The top two form elements are a text area for entering XSLT and a text entry field for the URL that points to the XML to be transformed. These elements are generated by the plug-in specific JSP. You can find the plug-in specific JSP in the XSLTPlugin.zip file available in the Download section. JSPs and the client side JavaScript framework did not change much between Versions 1 and 2, so please consult the earlier article for details on those subjects.

The second ViewBean is returned by the AuthHelper class by calling the restoreFromEntry method. The AuthHelper class is added in Version 2 to make it easy to add Basic and Form-based authentication support to any third party plug-in. The AuthHelper ViewBean generates all the form elements needed to gather credentials for the supported authentication methods. Later in this article you learn how to use the gathered credentials to access the URL containing the data to be transformed.

Figure 4 shows the generated form elements with Basic authentication selected.


Figure 4. Authentication form
Screenshot of authentication form with Basic selected as type of authentication.

Before leaving this topic, note that the AuthHelper instance is created by calling the static restoreFromEntry method and the first parameter is the IEditorContext instance. The AuthHelper uses the IEditorContext instance to automatically retrieve parameter values saved with the feed during earlier invocation of the editor. There is nothing for the caller to do!


displayPreviewPage method

The design of this example plug-in is similar to the plug-in described in the "An IBM Mashup Center plug-in to convert HTML to XML" article (see Resources). Users paste XSLT into the text box, provide a test URL, and then proceed to the preview page by clicking the Next button. The method to help generate the follow-on preview page is specified in the earlier renderEditor method where we have inserted a small chunk of Javascript code using form.setOnsubmit as shown in Listing 4. You can retrieve the JavaScript file providing the client side API by going to this URL: https://<yourserver>/mashuphub/client/scripts/hub/managers/Plugin.js The inserted JavaScript invokeServer will call the specified displayPreviewPage method through an AJAX call.

Listing 5 shows the body of the displayPreviewPage method.


Listing 5. displayPreviewPage method body
    entry.addAttribute(TransformConstants.PARAM_XSLT   , sXSLT );

    IParameter eparam = entry.createParameter();
    eparam.setName( TransformConstants.PARAM_XMLURL );
    eparam.setDefaultValue( sUrl  );
    eparam.setType("string");
    eparam.setPrompt("Y");
    entry.addParameter( eparam );

    AuthHelper authHelper = AuthHelper.createFromRequest( context
                                                        , AuthConstants.AUTH_METHOD_BASIC
                                                        , null );
    authHelper.saveParameters(context);
    authHelper.saveCredential( context );

The main purpose of the displayPreviewPage method is to return a second ViewBean (therefore JSP) to the framework for rendering an editor page to display the output of the XSLT transformation. Before returning the output from the XSLT transform, the method first has to save the parameters supplied by the user. The code in Listing 5 shows how the different pieces of information are saved. The XSLT is to be used in every feed generation, so it is saved as an attribute. The XML to transform can vary from invocation to invocation, so it is saved as a parameter. Note that Version 2 has a new method named createParameter that is used to return a parameter interface instance. For the authentication related information, the example re-instantiates a new instance of AuthHelper by calling the static createFromRequest method. This extracts and persists any user specified authentication information from the HTTP request.

The actual XSLT transform in preview is common to feed generation and is covered next. This wraps up the discussion of the Editor. Again, the complete source code is available in the Download section.


Implementing the feed generation

The TransformGeneratorPlugin class extends the BaseGenerator class and must implement the abstract method generateFeed. Similar to the renderEditor method, it takes a single parameter, which is an IGenerateContext interface instance. From the IGeneratorContext instance, you get the IRequestContext interface instance containing the information sent from the browser, and an IEntry instance containing all the information maintained by the framework for this feed instance.

Listing 6 contains the standard boilerplate for the generateFeed method.


Listing 6. renderEditor method body
public class TransformGeneratorPlugin extends BaseGenerator
{
    public IFeedContent generateFeed(IGeneratorContext context) throws GeneratorException
	{
        ILog    log         = context.getLog();
        IEntry  entry       = context.currentEntry();
        IRequestContext request = context.getRequestContext();
        ResourceBundle i18n = ResourceBundle.getBundle( TransformConstants.I18N_RESFILE
                                                      , context.getLocale());

To generate feeds, you first retrieve attributes containing configuration information saved during the editing process; for this plug-in, it is the XSLT entered into the text box during edit. Every invocation uses this same XSLT. The XML to transform can vary from invocation to invocation and is specified in the feed generation URL parameter named xmlurl. These are fairly straightforward operations against the IEntry and IRequestContext instances, so the relevant code snippet is not included in this article.

After retrieving the XML to transform, the implementation of the actual transformation is rather anti-climatic. As shown in Listing 7, it is fairly simple to initiate the XSLT transformation using JAXP and the XSLT engine shipped with the JDK.


Listing 7. renderEditor method body
    TransformerFactory tFactory = TransformerFactory.newInstance();
    Transformer transformer = tFactory.newTransformer(new StreamSource( rdrXSLT ));

    // Use the Transformer to apply the XSLT to the XML document
    Writer   writer = new StringWriter();
    transformer.transform( new StreamSource( rdrContent )
                         , new StreamResult( writer ));
    String  after = writer.toString();

What is of interest and new in this example, is how you retrieve the content from the caller provided URL. Instead of instantiating a java.net.URL instance directly, you first instantiate an instance of AuthHelper for this feed entry by passing in the context. You then obtain a connection from the AuthHelper instance by calling the connect method and passing in the URL. Under the covers, the AuthHelper instance generates the appropriate HTTP handshake according to the specified authentication method and using the credentials supplied during feed creation. Also, if the Mashup Center is configured to use a proxy, the request is directed through the specified proxy. Listing 8 shows the two lines of code needed to do all this.


Listing 8. renderEditor method body
    AuthHelper helper = AuthHelper.restoreFromEntry( context
                                                   , AuthConstants.AUTH_METHOD_BASIC
                                                   , null );
    conn = helper.connect(context, sUrl);

This concludes the tour of the implementation, now it is time to see the plug-in in action.


Sample usage

This section shows you how to put the plug-in to use. The first example considers the case where one of the elements in the input xml contains a large number of attributes. The idea is to convert them to elements so they can be displayed using widgets shipped with the product. This could be easily done using the data mashup editor's Transform operator. For each attribute, you would create an element in the output entry and then copy the value of the attribute over. However, if the number of attributes is high, this can become fairly tedious. An alternative would be to use XSLT. As an example, look at the sample attributes.xml file included in the XSLTPlugin.zip download and shown in Listing 9.


Listing 9. attribute.xml
<root>
<entry>
<info product='camera'
      price='40.00'
      instock='y'/>
</entry>
<entry>
<info product='USB drive'
      price='60.00'
      instock='n'/>
</entry>
</root>

Listing 10 is a fragment of the attribute.xsl sample XSLT included in the XSLTPlugin.zip download. This is the part that performs the attributes to elements transformation. The xsl:template element is used to locate the element of interest, which in this case is info. Once found, the xsl:for-each construct loops through all attributes selected using the pattern @*. For each attribute that matches the pattern, the xsl:element construct creates an element with the same name as the attribute. Lastly, the text value of the attribute is placed inside the newly created element.


Listing 10. attribute.xsl fragment
 
<xsl:template match="info">
    <info>
        <xsl:for-each select="@*">
            <xsl:element name="{name()}">
                <xsl:value-of select='.' />
            </xsl:element>
        </xsl:for-each>
    </info>
</xsl:template>

The next example exploits the richer conditional capabilities of XSLT to add HTML markup that enhances the display of a feed by using the DataViewer widget that is available "out-of-the-box" with the Mashup Center. Listing 11 shows the stocks.xml sample feed that is also included in the XSLTPlugin.zip download. The file was created by uploading a CSV file containing real times quote from the Yahoo! finance site.


Listing 11. stocks.xml
<entry xmlns="http://www.w3.org/2005/Atom">
  .........
  <content type="application/xml">
    <row xmlns="http://www.ibm.com/xmlns/atom/content/datarow/1.0">
      <col_A>BAC</col_A>
      <col_B>14.94</col_B>
      <col_C>11/6/2009</col_C>
      <col_D>11:23am</col_D>
      <col_E>-0.19</col_E>
      <col_F>14.94</col_F>
      <col_G>15.24</col_G>
      <col_H>14.84</col_H>
      <col_I>68841848</col_I>
    </row>
  </content>
</entry>

In this case, you want to display negative values in red to visually represent a drop in price. Also, the column names generated by the Mashup Center are not meaningful because the csv file does not contain a header row. So you also want to replace what is there with more meaningful names. Listing 12 is fragments from the stockColor.xsl sample XSLT file included in the XSLTPlugin.zip download. These are the parts of the file that make the changes described above and insert the HTML markup.


Listing 12. stockColor.xsl fragment
<xsl:template match="*" mode="rowChild">
  <xsl:choose>
    <xsl:when test="name()='col_A'" >
       <xsl:element name="Ticker">
          <xsl:value-of select="." />
       </xsl:element>
    </xsl:when>
    ................
    <xsl:when test="name()='col_E'" >
    <xsl:element name="Change">
    <xsl:choose>
      <xsl:when test="text() &lt; 0">
      &lt;font color="#FF0000" face="courier"&gt;<xsl:value-of select="." />&lt;/font&gt;
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
    </xsl:element>
    </xsl:when>
    ...............
  </xsl:choose>
</xsl:template>

The fragment in Listing 12 does not show the xsl:template statements that are used to locate the elements of interest (child elements of row). These child elements from row are passed to the above template for further processing. The xsl:choose and xsl:when statements correspond to the Java switch and case statements. There is one case (xsl:when) for each of the child elements of row. Non-numeric columns (for example, col_A) are renamed by creating a new element using xsl:element and copying the text value over. Numeric columns that could be negative (for example, col_E) are tested using a xsl:when statement to see if its text value is less than or greater than 0. If the value is negative, HTML markup to change the font color to red is inserted. Notice that the inserted markup needs to be escaped for the DataViewer to interpret it correctly. Note also that the comparison operators for "less than" and "greater or equal to" inside the xsl:if statement are also escaped to comply with XML rules.

One last thing to note before wrapping up is related to something that was skipped over when discussing the code in Listing 4. HTML text box unescapes XML entities &lt; and &gt; when text content is assigned to it programmatically (not when the user directly enters it into the text box). To ensure that the above XSLT file is rendered correctly when it is re-edited, the implementation escapes the XSLT content. For example, &lt; is changed to &amp;lt; so that it stays escaped when displayed.


Conclusion

You have just walked through the construction of a fairly complex plug-in involving multiple editor pages using the Mashup Center Version 2 APIs. To try out what you learned in this article, you could extend the current XLST plug-in to add parameter support. You could also start using XSLT transform by downloading the plug-in project and installing it on a Version 2 Mashup Center server.



Download

DescriptionNameSizeDownload method
Sample plug-in filesXSLTPlugin.zip181KBHTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the author

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.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management, Lotus, XML
ArticleID=454659
ArticleTitle=An IBM Mashup Center plug-in to perform XSLT transforms
publish-date=12102009
author1-email=louismau@us.ibm.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers