【问题标题】:Traversing a nested XML structure with XSLT template使用 XSLT 模板遍历嵌套的 XML 结构
【发布时间】:2015-04-14 12:10:33
【问题描述】:

我是 XSLT 的新手。我浏览了这个论坛中的不同解决方案,但我的问题有点不同。假设我们有一个 xml:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Transaction>
    <operation>DEBIT</operation>
    <autoRegistration>true</autoRegistration>
    <allowRecurrence>true</allowRecurrence>
    <network>VISA</network>
    <source>RANDOM</source>
    <origin>
        <merchant>ABC</merchant>
        <transactionId>1234</transactionId>
        <channel>SINGLE</channel>
        <country>DE</country>
    </origin>
    <customer>
        <number>338317</number>
        <eMail>someone@somewhere.de</eMail>
        <dateOfBirth>1975-06-15</dateOfBirth>
        <contact>
            <eMail>someone@somewhere.de</eMail>
            <phoneNumbers></phoneNumbers>
        </contact>
        <clientInfo>
            <ip>123.111.123.123</ip>
            <userAgent>Mozilla/5.0 (Windows NT 6.2; WOW64)</userAgent>
            <acceptHeader>*/*</acceptHeader>
        </clientInfo>
    </customer>
</Transaction>

假设我需要使用 XSLT 将其转换为 CSV。我需要我的 CSV,如下所示:

operation,allowRecurrence,source,merchant
DEBIT,true,RANDOM,ABC

嵌套的 xml 元素越多,现实世界的问题就越复杂。我应该如何为这样的问题设计我的 XSLT,以便它处理多层嵌套的 XML 元素并为我准备一个 CSV。 到目前为止,我已经设法整理:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>

    <xsl:variable name="delimiter" select="','"/>

    <!-- define an array containing the fields we are interested in -->
    <xsl:variable name="fieldArray">
        <field>operation</field>
        <field>allowRecurrence</field>
        <field>source</field>
        <field>merchant</field>
    </xsl:variable>
    <xsl:param name="fields" select="document('')/*/xsl:variable[@name='fieldArray']/*"/>

    <xsl:template match="/">
        <xsl:variable name="currNode" select="."/>
        <!-- output the header row -->
        <xsl:for-each select="$fields">
            <xsl:if test="position() != 1">
                <xsl:value-of select="$delimiter"/>
            </xsl:if>
            <xsl:value-of select="."/>
        </xsl:for-each>

        <!-- output newline -->
    <xsl:text>
</xsl:text>
        <xsl:for-each select="$fields" >
            <xsl:if test="position() != 1">
                <xsl:value-of select="$delimiter"/>
            </xsl:if>
            <xsl:value-of select="$currNode/*/*[name() = current()]"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

我被困在 &lt;xsl:value-of select="$currNode/*/*[name() = current()]"/&gt; 的逻辑上...我如何在这个循环中改变 XML 元素嵌套的级别。

【问题讨论】:

    标签: xml csv xslt


    【解决方案1】:

    XML 文档不是“任意的”;它们遵循预定义的模式。您最好的策略是将您的 XSLT 定制为预期的模式。在您的示例中,这意味着:

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="UTF-8"/>
    
    <xsl:template match="/Transaction">
        <xsl:text>operation,allowRecurrence,source,merchant,eMail&#10;</xsl:text>
        <xsl:value-of select="operation"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="allowRecurrence"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="source"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="origin/merchant"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="customer/eMail"/>
    </xsl:template>
    
    </xsl:stylesheet>
    

    当有多个同名节点时,您遍历文档、查找名为“xyx”的节点的想法会失败。例如,您的 XML 有两个 eMail 节点,而您的方法永远不会到达 customer/contact/eMail 的那个。

    【讨论】:

    • 也许这就是 molbal 对批评的反应?当然 +1。
    • @molbal 您应该将您的评论发送给 Mathias。
    猜你喜欢
    • 2011-09-06
    • 2021-12-24
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-07
    相关资源
    最近更新 更多