2011-04-04 51 views
0

我这里有一个XML文件转换复杂的XML为csv ...使用XSL使用循环功能

<?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</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> 

我要创建这种格式的csv文件的输出..

classname1, outbound. 

classname1, outbound. 

.    . 

.    . 

classname1, inbound. 

.    . 

.    . 

classname2, outbound. 

.    . 

classname2, inbound. 

和等等。

现在我面临的挑战是每个班级的入站和出站的数量是不同的和不同的。所以我必须指定循环。此外,我只需要类名称包含“com”关键字或字符串里面不包名称,功能名称全部。我需要做这个xsl,以便对于所有类似的xml我生成我可以将其更改为csv表格为我进一步的数据,我需要的过程。

在xsl我创建如下所示,但我STIL面临着一些缺陷和问题

<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> 

和输出作为

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 

状排列的表几乎发生,但具有包名称问题仍然来坚持一流的名字,并在最后一些不必要的java字符串串。 希望得到指导和帮助。谢谢

+0

我有问题完全显示我的xsl。我试图完全粘贴它,但它只是部分。对此而言。 – Memoc 2011-04-04 03:09:22

+0

你可以缩进所有的代码4个空格 - 在编辑器中使用'{}'按钮来做到这一点。我为你修好了。 – 2011-04-04 03:34:05

+0

您的输出不清楚。提供一些与您提供的输入相匹配的输出。 – 2011-04-04 03:36:06

回答

2

那么,你不必做任何明确的循环。你可以做你想用模板做的所有事情。

要有效编写XSLT,您必须考虑转换。想一想,“我想把输入中的某些东西转换成输出中的某些东西。”那些东西是什么?你没有在你的问题中阐述他们,你可能没有在你的设计中阐述他们。

看来你想要的是将每个package元素转换为输出中的一行。所以你需要一个模板。每行的第一件事是包名(即name元素的文本内容),最后一件事是换行符。所以用这个启动:

<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> 

如果你运行你的输入文档中变换,(假设你已经把它变成一个实际的样式表),你应该得到所有的包名作为输出的一个简单的列表。

现在您想要将outboundinbound元素的内容添加为每行上额外的以逗号分隔的元素。什么是转型?如果confirmed属性等于no,则这些元素中的每一个都需要转换为包含逗号,元素文本内容和星号的文本。

这很容易实现:只需创建一个模板这些元素,并将其应用于package模板中。

<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> 

两件事情是关于这个方法来设计和实施重要的:首先,你使用模板来改变既然你只需要其文本内容与con.开始出现的元素,应用模板时添加谓词节点,而不是尝试使用不是为其设计的语言使用过程式编程。

其次,你只是在转换你明确选择的节点。现在,在输出结束时得到垃圾的原因是,您已经将模板应用于您认为不应用于它们的节点:您没有创建应用于文档根目录的模板,并且所以XSLT处理器将内置模板应用到它找到的每个元素。

+0

+1以获得很好的答案。 – 2011-04-04 13:09:00

+0

+1与OP呆在一起,直到最后一段... – 2011-04-04 13:49:23