开发者

Convert complex xml to csv using xsl using looping function

I having a xml file here..

<?xml version="1.0" encoding="utf-8" ?>

<!DOCTYPE dependencies SYSTEM "http://depfind.sourceforge.net/dtd/dependencies.dtd">

<dependencies>
    <package confirmed="yes">
        <name>com.infopro.Dependency</name>
        <class confirmed="yes">
            <name>com.infopro.Dependency.A</name>
            <outbound type="class" confirmed="no">java.lang.Object</outbound>
            <outbound type="class" confirmed="no">javax.ejb.Stateless</outbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.B()</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.a</inbound>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.A.A()</name>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.A.b</outbound>
                <outbound type="class" confirmed="yes">com.infopro.Dependency.B</outbound>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.B.B()</outbound>
                <outbound type="feature" confirmed="no">java.lang.Object.Object()</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.B()</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.A.b</name>
                <outbound type="class" confirmed="yes">com.infopro.Dependency.B</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.A()</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.A.check(java.lang.String, java.lang.String)</name>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.A.stat</outbound>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.doStatus()</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.A.doStatus()</name>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.A.check(java.lang.String, java.lang.String)</outbound>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.A.name</outbound>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.A.user_id</outbound>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.A.name</name>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.doStatus()</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.A.stat</name>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.check(java.lang.String, java.lang.String)</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.A.user_id</name>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.doStatus()</inbound>
            </feature>
        </class>
        <class confirmed="yes">
            <name>com.infopro.Dependency.B</name>
            <outbound type="class" confirmed="yes">com.infopro.Dependency.C</outbound>
            <outbound type="class" confirmed="no">java.lang.Object</outbound>
            <outbound type="class" confirmed="no">javax.ejb.Stateless</outbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.A()</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.b</inbound>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.B.B()</name>
                <outbound type="class" confirmed="yes">com.infopro.Dependency.A</outbound>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.A.A()</outbound>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.B.a</outbound>
                <outbound type="feature" confirmed="no">java.lang.Object.Object()</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.A()</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.B.a</name>
                <outbound type="class" confirmed="yes">com.infopro.Dependency.A</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.B()</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.B.check(java.lang.String, java.lang.String)</name>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.B.stat</outbound>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.doStatus()</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.B.doStatus()</name>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.B.check(java.lang.String, java.lang.String)</outbound>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.B.name</outbound>
                <outbound type="feature" confirmed="yes">com.infopro.Dependency.B.user_id</outbound>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.B.name</name>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.doStatus()</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.B.stat</name>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.check(java.lang.String, java.lang.String)</inbound>
            </feature>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.B.user_id</name>
                <outbound type="class" confirmed="no">java.lang.String</outbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.doStatus()</inbound>
            </feature>
        </class>
        <class confirmed="yes">
            <name>com.infopro.Dependency.C</name>
            <outbound type="class" confirmed="no">java.lang.Object</outbound>
            <outbound type="class" confirmed="no">javax.ejb.Remote</outbound>
            <inbound type="class" confirmed="yes">com.infopro.Dependency.B</inbound>
            <feature confirmed="yes">
                <name>com.infopro.Dependency.C.doStatus()</name>
            </feature>
        </class>
    </package>
    <package confirmed="no">
        <name>java.lang</name>
        <class confirmed="no">
            <name>java.lang.Object</name>
            <inbound type="class" confirmed="yes">com.infopro.Dependency.A</inbound>
            <inbound type="class" confirmed="yes">com.infopro.Dependency.B</inbound>
            <inbound type="class" confirmed="yes">com.infopro.Dependency.C</开发者_Go百科inbound>
            <feature confirmed="no">
                <name>java.lang.Object.Object()</name>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.A()</inbound>
                <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.B()</inbound>
            </feature>
        </class>
        <class confirmed="no">
            <name>java.lang.String</name>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.check(java.lang.String, java.lang.String)</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.doStatus()</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.name</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.stat</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.A.user_id</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.check(java.lang.String, java.lang.String)</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.doStatus()</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.name</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.stat</inbound>
            <inbound type="feature" confirmed="yes">com.infopro.Dependency.B.user_id</inbound>
        </class>
    </package>
    <package confirmed="no">
        <name>javax.ejb</name>
        <class confirmed="no">
            <name>javax.ejb.Remote</name>
            <inbound type="class" confirmed="yes">com.infopro.Dependency.C</inbound>
        </class>
        <class confirmed="no">
            <name>javax.ejb.Stateless</name>
            <inbound type="class" confirmed="yes">com.infopro.Dependency.A</inbound>
            <inbound type="class" confirmed="yes">com.infopro.Dependency.B</inbound>
        </class>
    </package>
</dependencies>

I want to create a output of csv file in this format..

classname1, outbound.

classname1, outbound.

.             .

.             .

classname1, inbound.

.             .

.             .

classname2, outbound.

.             .

classname2, inbound.

and so on..

Now the challenge for me is the quantity of inbound and outbound for each class are different and varies. so i have to specify looping for that. And also i just need class name contains "com" keyword or string inside excluding package name, feature name all. I need do this xsl so that for all similiar xml i generate i can change it to csv table form for my further process of data that i needed.

The xsl i created shown below but i stil facing some bugs and problems

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/> 


    <xsl:template match="class[contains(.//text(), 'com')]">
        <xsl:text></xsl:text><xsl:value-of select="name"/><xsl:if test="@confirmed='no'"> *</xsl:if><xsl:text> </xsl:text>
        <xsl:for-each select="outbound[contains(.//text(), 'com')]">
            <xsl:text disable-output-escaping="yes">   , </xsl:text><xsl:value-of select="."/><xsl:if test="@confirmed='no'"> *</xsl:if><xsl:text>
</xsl:text>
        </xsl:for-each>
        <xsl:for-each select="inbound[contains(.//text(), 'com')]">
            <xsl:text disable-output-escaping="yes">   , </xsl:text><xsl:value-of select="."/><xsl:if test="@confirmed='no'"> *</xsl:if><xsl:text>
</xsl:text>
        </xsl:for-each>
    </xsl:template>  
</xsl:stylesheet>

And the output as

com.infopro.Dependencycom.infopro.Dependency.A                               , com.infopro.Dependency.B.B()
                                                                             , com.infopro.Dependency.B.a
com.infopro.Dependency.B                                                     , com.infopro.Dependency.C
                                                                             , com.infopro.Dependency.A.A()
                                                                             , com.infopro.Dependency.A.b
com.infopro.Dependency.C                                                     , com.infopro.Dependency.B
java.langjava.lang.Objectcom.infopro.Dependency.Acom.infopro.Dependency.Bcom.infopro.Dependency.Cjava.lang.Object.Object()com.infopro.Dependency.A.A()com.infopro.Dependency.B.B()java.lang.Stringcom.infopro.Dependency.A.check(java.lang.String, java.lang.String)com.infopro.Dependency.A.doStatus()com.infopro.Dependency.A.namecom.infopro.Dependency.A.statcom.infopro.Dependency.A.user_idcom.infopro.Dependency.B.check(java.lang.String, java.lang.String)com.infopro.Dependency.B.doStatus()com.infopro.Dependency.B.namecom.infopro.Dependency.B.statcom.infopro.Dependency.B.user_idjavax.ejbjavax.ejb.Remotecom.infopro.Dependency.Cjavax.ejb.Statelesscom.infopro.Dependency.Acom.infopro.Dependency.B

The table like arrangement almost occur but having problem with package name still coming stick with first class name, and some long string of unwanted java strings at the end. Hope for guidance and help. thank you


Well, you don't have to do any explicit looping. You can do everything you're trying to do with templates.

To effectively write XSLT, you have to think in terms of transformation. Think, "I want to transform some thing in the input into some thing in the output." What are those things? You haven't articulated them in your question, and it's possible that you haven't articulated them in your design.

It seems like what you want is to convert each package element into a line in the output. So you'll need a template for that. The first thing on each row is the package name (i.e. the text content of the name element), and the last thing will be a newline. So start with this:

<xsl:template match="/">
   <xsl:apply-templates select="dependencies/package"/>
</xsl:template>

<xsl:template match="package">
   <xsl:value-of select="name/text()"/>
   <!-- something will go in here -->
   <xsl:text>&#x0a;</xsl:text>
</xsl:template>

If you run that transform in your input document, (assuming you've put it into an actual stylesheet), you should get a simple list of all of the package names as the output.

Now you want to add the contents of the outbound and inbound elements as additional comma-separated elements on each line. What's the transformation? Each of these elements needs to be transformed into a piece of text containing a comma, the element's text content, and an asterisk if the confirmed attribute equals no.

That's easily accomplished: just create a template these elements, and apply them within the package template. Since you only want the elements whose text content begins with con. to appear, add predicates when applying the templates:

<xsl:template match="package">
   <xsl:value-of select="name/text()"/>
   <xsl:apply-templates select="output[contains(text(), '.com')]"/>
   <xsl:apply-templates select="input[contains(text(), '.com')]"/>
   <xsl:text>&#x0a;</xsl:text>
</xsl:template>

<xsl:template match="output|input">
   <xsl:text>, </xsl:text>
   <xsl:value-of select="text()"/>
   <xsl:if test="@confirmed='no'">
      <xsl:text> *</xsl:text>
   </xsl:text>
</xsl:text>

Two things that are important about this approach to design and implementation: First, you are using templates to transform nodes, instead of trying to use procedural programming in a language that isn't designed for it.

Second, you're only transforming the nodes that you've explicitly selected. The reason you're getting garbage at the end of your output now is that you've applied templates to nodes that you didn't think you were applying them to: you didn't create a template that's applied to the document root, and so the XSLT processor is applying built-in templates to every element it finds.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜