XSLT 到 CSV - 如何控制具有不同属性值的同一元素的顺序?

XSLT to CSV - How to control the order of the same element with different attribute values?

我是 XSLT 的新手,我需要弄清楚如何根据 CSV 文件的属性值以特定顺序从 XML 文件中检索重复元素。我的结果文档是一个 CSV 文件,我最终需要将其内容导入 SQL 服务器 tables。因此,CSV 文件中检索到的元素的顺序很重要,因为它们需要匹配定义为 headers.

的 table 列

我的问题出现在 Project Content_Detail 元素中,该元素以不同的语言存在并且可以以任何顺序出现在 XML 源代码中。我只需要首先提取带有 Title, Goal 元素的德文版本,然后是英文版本元素。

我使用 SSIS 和 MS Visual Studio 2019 将我的 XML 转换为 CSV 文件。 MS Visual Studio 仅支持 XSLT 1.0。

这是我的 XML 文件(已编辑):

<?xml version="1.0" encoding="utf-8"?>
<dta:Projects xmlns:dta="http://domain.test/dta">
  <dta:Project>
    <dta:Core-Basis>
      <dta:Goal>1672</dta:Goal>
    </dta:Core-Basis>
    <dta:Basisinfo>
      <dta:Content>
        <dta:Content_Detail Lang="de">
          <dta:Title>Wirtschaft</dta:Title>
          <dta:Aim>Steigerung</dta:Aim>
        </dta:Content_Detail>
        <dta:Content_Detail Lang="en">
          <dta:Title>Economy</dta:Title>
        </dta:Content_Detail>
      </dta:Content>
    </dta:Basisinfo>
  </dta:Project>
  <dta:Project >
    <dta:Core-Basis>
      <dta:Goal>2035</dta:Goal>
    </dta:Core-Basis>
    <dta:Basisinfo>
      <dta:Content>
        <dta:Content_Detail Lang="en">
          <dta:Title>Environmental Protection</dta:Title>
          <dta:Aim>Facilitation</dta:Aim>
        </dta:Content_Detail>
        <dta:Content_Detail Lang="de">
          <dta:Title>Naturschutz</dta:Title>
        </dta:Content_Detail>
      </dta:Content>
    </dta:Basisinfo>
  </dta:Project >
</dta:Projects>

这是我的 XSLT 文件(已编辑)。我尝试向 xsl:if 块添加大量顺序和排序参数,但我还没有想出一个可行的解决方案:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dta="http://domain.test/dta" exclude-result-prefixes="dta">
<xsl:output method="text" encoding="UTF-8" indent="no"/>
    <xsl:template match="/">
        <xsl:text>DTA_Goal;DTA_Title_de;DTA_Aim_de;DTA_Title_en;DTA_Aim_en;&#xA;</xsl:text>
        <xsl:apply-templates mode="find_content"/>
    </xsl:template>
    <xsl:template match="text()|@*" mode="find_content"/>
    <xsl:template match="dta:Project" mode="find_content">
        <xsl:value-of select="concat(dta:Core-Basis/dta:Goal,';')"/>
        <xsl:apply-templates mode="find_content"/>
    </xsl:template>
    <xsl:template match="dta:Content_Detail" mode="find_content">
        <xsl:if test="@Lang='de'">
            <xsl:value-of select="concat(dta:Title,';')"/>
            <xsl:value-of select="concat(dta:Aim,';')"/>
        </xsl:if>
        <xsl:if test="@Lang='en'">
            <xsl:value-of select="concat(dta:Title,';')"/>
            <xsl:value-of select="concat(dta:Aim,'&#xA;')"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

这是我到目前为止的 CSV 输出,没有根据语言值属性对 Content_detail 进行排序:

DTA_Goal;DTA_Title_de;DTA_Aim_de;DTA_Title_en;DTA_Aim_en;
1672;Wirtschaft;Steigerung;Economy;
2035;Environmental Protection;Facilitation
Naturschutz;;

这是我需要的:

DTA_Goal; DTA_Title_de; DTA_Aim_de; DTA_Title_en; DTA_Aim_en;
1672;Wirtschaft;Steigerung;Economy;;
2035;Naturschutz;;Environmental Protection;Facilitation;

由于我不是专业程序员,因此非常感谢对我的其余代码的任何帮助或评论。

在您的输入中,dta:Project 个元素之一有一个 dta:Core-Basis 个子元素,而另一个元素有 dta:Core-Basisdaten 个。假设这是一个错误*,您可以简单地通过以下方式生成所需的输出:

XSLT 1.0

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

<xsl:template match="/dta:Projects">
    <!-- header -->
    <xsl:text>DTA_Goal;DTA_Title_de;DTA_Aim_de;DTA_Title_en;DTA_Aim_en;&#10;</xsl:text>
    <!-- data -->
    <xsl:for-each select="dta:Project">
        <xsl:value-of select="dta:Core-Basis/dta:Goal"/>
        <xsl:text>;</xsl:text>
        <!-- de -->
        <xsl:variable name="content-de" select="dta:Basisinfo/dta:Content/dta:Content_Detail[@Lang='de']" />
        <xsl:value-of select="$content-de/dta:Title"/>
        <xsl:text>;</xsl:text>
        <xsl:value-of select="$content-de/dta:Aim"/>
        <xsl:text>;</xsl:text>
        <!-- en -->
        <xsl:variable name="content-en" select="dta:Basisinfo/dta:Content/dta:Content_Detail[@Lang='en']" />
        <xsl:value-of select="$content-en/dta:Title"/>
        <xsl:text>;</xsl:text>
        <xsl:value-of select="$content-en/dta:Aim"/>
        <xsl:text>;</xsl:text>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

(*) 如果不是,则更改:

<xsl:value-of select="dta:Core-Basis/dta:Goal"/>

至:

<xsl:value-of select="(dta:Core-Basis|dta:Core-Basisdaten)/dta:Goal"/>

P.S。不确定为什么需要在每行末尾添加 ;