Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XSLT-将XML嵌套到CSV输出_Xml_Csv_Xslt - Fatal编程技术网

XSLT-将XML嵌套到CSV输出

XSLT-将XML嵌套到CSV输出,xml,csv,xslt,Xml,Csv,Xslt,我正在尝试使用XSLT将XML文件转换为CSV。我有以下要转换的XML文件(手动简化版本)。每个XML文件可以包含N个记录,其中N个可能不同 <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> <report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <reportheader> <name>REPORT 1&l

我正在尝试使用XSLT将XML文件转换为CSV。我有以下要转换的XML文件(手动简化版本)。每个XML文件可以包含N个记录,其中N个可能不同

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<reportheader>
<name>REPORT 1</name>
<version>v1</version>
</reportheader>
<recordtype>
    <account>
    <accountname>B</accountname>
    </account>
    <record>
    <time>12:00:00</time>
    <qty>10</qty>
    <price>20</price>
    </record>
    <record>
    <time>16:00:00</time>
    <qty>20</qty>
    <price>10</price>
    </record>   
</recordtype>
<recordtype>
    <account>
    <accountname>A</accountname>
    </account>
    <record>
    <time>16:00:00</time>
    <qty>5</qty>
    <price>10</price>
    </record>   
</recordtype>
</report>
我目前的方法是使用两个脚本。一个输出所有根节点和直接父节点的XSLT。在第二个XSLT中,我计算记录节点的数量,并在csv列名中循环N次。然后我寻找匹配/记录/时间[N]的示例。当前的方法大量借鉴了:

我目前的方法有两个问题。1,它假定每个记录始终具有每个可用字段。2.我无法为记录分配正确的帐户,因为100条记录可能只有6个帐户。它们在xml文件中“松散耦合”的方式使我的方法无效


有人能帮我找到一种更稳健、更高效的方法吗?提前感谢。

您可以通过使用
祖先
轴查找近亲值一次完成

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/">
    <xsl:text>name|version|accountname|time|qty|price&#xd;&#xa;</xsl:text>
    <xsl:apply-templates select="//record"/>
  </xsl:template>
  <xsl:template match="record">
    <xsl:value-of select="ancestor::report/reportheader/name"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="ancestor::report/reportheader/version"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="ancestor::recordtype/account/accountname"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="time"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="qty"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="price"/>
    <xsl:text>&#xd;&#xa;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

名称|版本|账户名称|时间|数量|价格| xd
;
|
|
|
|
|

;


;
你也可以试试。

谢谢,我几乎可以无缝地调整这个答案,以适应扩展的用例。如果我可以问一个小的后续问题,我应该在哪里插入一个名称空间“x:”,以便它们与祖先轴查找一起工作?@GdvJ我想这只是
祖先::x:name
对!我只需要记住在树中的每个元素前面加上“x:”,而不仅仅是在开头。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/">
    <xsl:text>name|version|accountname|time|qty|price&#xd;&#xa;</xsl:text>
    <xsl:apply-templates select="//record"/>
  </xsl:template>
  <xsl:template match="record">
    <xsl:value-of select="ancestor::report/reportheader/name"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="ancestor::report/reportheader/version"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="ancestor::recordtype/account/accountname"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="time"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="qty"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="price"/>
    <xsl:text>&#xd;&#xa;</xsl:text>
  </xsl:template>
</xsl:stylesheet>
 <xsl:output method="text"/>
    <xsl:template match="report">
        <xsl:for-each select="reportheader">
            <xsl:value-of select="name/local-name(),version/local-name(), following-sibling::recordtype[1]/account/accountname/local-name(),following-sibling::recordtype[1]/record[1]/time/local-name(),following-sibling::recordtype[1]/record[1]/qty/local-name(),following-sibling::recordtype[1]/record[1]/price/local-name()" separator="|"/>
            </xsl:for-each>
        <xsl:for-each select="recordtype/record">
            <xsl:text>&#x0a;</xsl:text>
            <xsl:value-of select=" ancestor::report/reportheader/name,ancestor::report/reportheader/version, preceding-sibling::account/accountname,time,qty,price" separator="|"/>

        </xsl:for-each>
    </xsl:template>
You may also try it.