首页 > 解决方案 > 如果 XML 中没有标签,如何在使用 XSLT 转换为 CSV 时添加名称?

问题描述

我有两种情况,当我必须处理 XML 并使用 XSLT 创建 CSV 时,我无法继续前进。输入文件:

<?xml version="1.0" encoding="utf-8"?>
<families>
    <family id ="1">
        <type_client>
            <code>1</code>
            <code>2</code>
        </type_client>
        <family_client>
            <code>99</code>
            <code>98</code>
        </family_client>
    </family>
    <family id ="2">
        <type_client>
            <code>3</code>
            <code>4</code>
        </type_client>
        <family_client>
            <code>88</code>
            <code>89</code>
        </family_client>
    </family>
</families>

场景 1:在将 XML 文件转换为 CSV 时,无论标签是否存在,我都必须添加标签名称“ family_name ”(即,如果标签存在,标签名称应该出现,否则自定义名称应该出现)。如果标签存在,local-name() 将给出名称,否则不会给出。如果标签不存在,如何添加标签名称?

场景 2<type_client>有重复的子标签,即<code>99</code><code>98</code>(来自示例)。我必须添加与此标签一样多的记录,<code>即,从示例中我必须添加 2 条记录。两种方案的预期输出: type_client.csv

id,family_name,type_client
1,,1
1,,2
2,,3
2,,4

family_client.csv

id,family_name,family_client
1,,99
1,,98
2,,88
2,,89

XSLT:

<xsl:stylesheet xmlns:xsl="w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes" method="text"/>
    <xsl:template match="families">
        <xsl:result-document href="type.txt">
            <xsl:value-of select="family[1]/@id/local-name(),family[1]/family_name/local-name(),family[1]/type_client/local-name()" separator=","/>
            <xsl:text>&#x0A;</xsl:text>
            <xsl:for-each select="family">
                <xsl:value-of select="@id,family_name,type_client/code" separator=","/>
                <xsl:text>&#x0A;</xsl:text>
            </xsl:for-each>
        </xsl:result-document>
    </xsl:template>
</xsl:stylesheet>

下面是我得到的输出:

id,family_name,type_client
1,Husband's Family,1,2
2,Wife's Family,3,4

注意:这里family_name的值是手动添加的,以显示如果它有数据应该如何出现,否则在阅读评论后,当标签不存在时,标签作为名称应该出现。

预期输出:

id,family_name,type_client
1,Husband's Family,1
1,Husband's Family,2
2,Wife's Family,3
2,Wife's Family,4

标签: xmlcsvxslt

解决方案


family_name如果不存在,我不认为这是添加的情况。如果值不存在,则确保在 CSV 中输出值。

而不是这样做...

<xsl:value-of select="@id,family_name,type_client/code" separator=","/>

你可以这样做(||连接运算符在哪里)

<xsl:value-of select="@id,(family_name||''),type_client/code" separator=","/>

所以如果不存在(family_name||'')则返回一个空字符串。family_name如果family_name确实存在,则连接一个空字符串不会影响它。

标题行的创建似乎有点过于复杂。而不是这样做......

<xsl:value-of select="family[1]/@id/local-name(),family[1]/family_name/local-name(),family[1]/type_client/local-name()" separator=","/>

您可以这样做,因为local-name()当您已经知道名称是什么时使用没有意义(因为您已在 xpath 表达式中对其进行硬编码)

<xsl:text>id,family_name,type_client</xsl:text>

对于您的方案 2,解决方案是使用xsl:for-each而不family/type_client/code只是家庭

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes" method="text"/>
    <xsl:template match="families">
        <xsl:result-document href="type.txt">
            <xsl:text>id,family_name,type_client&#x0A;</xsl:text>
            <xsl:for-each select="family/type_client/code">
                <xsl:value-of select="../../@id,(../family_name||''),." separator=","/>
                <xsl:text>&#x0A;</xsl:text>
            </xsl:for-each>
        </xsl:result-document>
    </xsl:template>
</xsl:stylesheet>

推荐阅读