首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用xsl使用循环函数将复杂的xml转换为csv

使用xsl使用循环函数将复杂的xml转换为csv
EN

Stack Overflow用户
提问于 2011-04-04 11:00:54
回答 1查看 1.3K关注 0票数 0

我这里有一个xml文件..

代码语言:javascript
复制
<?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文件的输出。

代码语言:javascript
复制
classname1, outbound.

classname1, outbound.

.             .

.             .

classname1, inbound.

.             .

.             .

classname2, outbound.

.             .

classname2, inbound.

以此类推..

现在我面临的挑战是,每个班级的入站和出站数量都不同,而且各不相同。所以我必须为它指定循环。另外,我只需要在类名中包含"com“关键字或字符串,不包括包名,特性名。我需要这样做xsl,以便对于我生成的所有类似的xml,我可以将其更改为csv表形式,以便进一步处理所需的数据。

我创建的xsl如下所示,但我仍然面临一些bug和问题

代码语言:javascript
复制
<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>

输出结果为

代码语言:javascript
复制
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字符串。希望能得到指导和帮助。谢谢

EN

回答 1

Stack Overflow用户

发布于 2011-04-04 15:23:24

嗯,你不需要做任何显式的循环。你可以对模板做任何你想做的事情。

要有效地编写XSLT,必须从转换的角度进行考虑。想一想,“我想把输入中的一些东西转换成输出中的一些东西。”这些是什么东西?你没有在你的问题中清楚地表达它们,也有可能你在你的设计中没有表达它们。

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

代码语言:javascript
复制
<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模板中应用它们。由于您只希望显示文本内容以con.开头的元素,因此应在应用模板时添加谓词:

代码语言:javascript
复制
<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>

关于这种设计和实现方法,有两点很重要:首先,您使用模板来转换节点,而不是试图在一种不适合它的语言中使用过程化编程。

其次,您只需要转换显式选择的节点。现在您在输出的末尾得到垃圾信息的原因是,您已经将模板应用到了您认为没有应用它们的节点:您没有创建应用于文档根目录的模板,因此XSLT处理器会将内置模板应用于它找到的每个元素。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5534190

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档