【问题标题】:Merge Elements (XML) With Same ID to txt file using XSLT使用 XSLT 将具有相同 ID 的元素 (XML) 合并到 txt 文件
【发布时间】:2021-12-30 00:16:30
【问题描述】:

我有一个任务,我需要遍历 XML 文档并合并具有相同 ID 的元素/节点。输出应该是一个 csv 文件(用于进一步处理),其中每一行都有固定的长度。根据节点的值,该值需要放置在输出中的某个位置。

这是一个XML示例

<root>
    <User>
        <UserID>55555</UserID>
        <Value>Active</Value>
    </User>
    <User>
        <UserID>55555</UserID>
        <Value>Admin</Value>
    </User>
    <User>
        <UserID>55555</UserID>
        <Value>Eligible</Value>
    </User>
    <User>
        <UserID>123456</UserID>
        <Value>Active</Value>
    </User>
</root>

我的想要的输出是:

User ID, Active, Admin, Eligible
55555, Y, Y, Y,
123456, Y, N, N,

请注意,这些值始终相同(活动、管理员和合格),但用户可以拥有不同数量的值,如示例中所示。

目前这是我得到的:

    <xsl:template match="/root">
        <Header>
            <xsl:text>User ID</xsl:text>
            <xsl:value-of select="$comma"/>
            
            <xsl:text>Active</xsl:text>
            <xsl:value-of select="$comma"/>
            
            <xsl:text>Admin</xsl:text>
            <xsl:value-of select="$comma"/>
            
            <xsl:text>Eligible</xsl:text>
            <xsl:text>&#xa;</xsl:text>
        </Header>
            <xsl:for-each-group select="User" group-by="UserID"> 
                
                <!-- User ID -->
                <xsl:value-of select="UserID"/>
                <xsl:value-of select="$comma"/>
                
                <xsl:for-each-group select="current-group()" group-by="Value">
                    <xsl:value-of select="current-grouping-key()"/>
                    <xsl:value-of select="$comma"/>
                </xsl:for-each-group>
                
                <xsl:value-of select="$lineFeed"/>
            </xsl:for-each-group>
    </xsl:template>

该组并选择正确的元素,但随后我需要将它们放在正确的标题下(例如具有所需输出的 ​​axample)。

任何人都可以在这里指出正确的方向吗?任何帮助将不胜感激。

【问题讨论】:

  • 这很难理解。您是在问“詹姆斯”和“纽约”只是相应列中有值的指标吗?如果是这样,姓氏列的指示符是什么?此外,您说“输出应该是一个 csv 文件”,但是您说“每行都有固定长度”。而且您的样式表似乎正在生成一个制表符分隔的文件(带有 XML 标头!)。这些是三(或四)种不同的东西。
  • 这只是示例。使用“姓名”“姓氏”和“城市”来显示它并不是最好的方式。这个想法是应该在这些标题下的字段始终具有相同的值。因此,如果 James 那么这应该在 Name 等下。“Lastname”的指示符将是 Peterson。正如您所指出的,我更改了变量的名称以反映逗号而不是错误的制表符。

标签: xml csv xslt xslt-2.0 xslt-grouping


【解决方案1】:

如果我理解正确(如果非常大!),你想做这样的事情:

XSLT 2.0

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

<xsl:template match="/root">
    <!-- header -->
    <xsl:text>User ID, Active, Admin, Eligible&#10;</xsl:text>
    <!-- rows -->
    <xsl:for-each-group select="User" group-by="UserID"> 
        <!-- User ID -->
        <xsl:value-of select="UserID"/>
        <xsl:text>, </xsl:text>
        <!-- Active -->
        <xsl:value-of select="if (current-group()/Value[.='Active']) then 'Y' else'N'"/>
        <xsl:text>, </xsl:text>
        <!-- Admin -->
        <xsl:value-of select="if (current-group()/Value[.='Admin']) then 'Y' else'N'"/>
        <xsl:text>, </xsl:text>
        <!-- Eligible -->
        <xsl:value-of select="if (current-group()/Value[.='Eligible']) then 'Y' else'N'"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>

或者更简洁:

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

<xsl:template match="/root">
    <!-- header -->
    <xsl:text>User ID, Active, Admin, Eligible&#10;</xsl:text>
    <!-- rows -->
    <xsl:for-each-group select="User" group-by="UserID"> 
        <xsl:value-of select="UserID, for $t in ('Active', 'Admin', 'Eligible') return if (current-group()/Value[.=$t]) then 'Y' else 'N'" separator=", "/>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>

请注意,结果与您发布的结果略有不同:每条记录中没有尾随逗号。

【讨论】:

  • 感谢迈克尔的回复。这正是我一直在寻找的!我看到您注意到我编辑了问题以更清晰,并且您调整了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
  • 2021-12-29
  • 2012-01-25
相关资源
最近更新 更多