使用 XSLT 2.0 的两阶段转换

发布于 2024-11-03 09:52:06 字数 2168 浏览 0 评论 0 原文

我正在尝试将 CSV 文件作为输入并将其转换为 XML。我是 XSLT 新手,我找到了一种将 CSV 转换为 XML 的方法(使用 Andrew Welch) 就像这样:

输入 CSV 文件:

car manufacturer,model,color,price,inventory
subaru,outback,blue,23195,54
subaru,forester,silver,20495,23

我的输出 XML 是:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
   <row>
      <column name="car manufacturer">subaru</column>
      <column name="model">outback</column>
      <column name="color">blue</column>
      <column name="price">23195</column>
      <column name="inventory">54</column>
   </row>
   <row>
      <column name="car manufacturer">subaru</column>
      <column name="model">forester</column>
      <column name="color">silver</column>
      <column name="price">20495</column>
      <column name="inventory">23</column>
   </row>
</rows>

我想要的输出实际上类似于:

<stock>
   <model>
      <car>subaru outback</car>
      <color>blue</color>
      <price>23195</price>
      <inventory>54</inventory>
   </model>
   <model>
      <car>subaru forester</car>
      <color>silver</color>
      <price>20495</price>
      <inventory>23</inventory>
   </model>
</stock>

我读到的是,最好使用两个相变。 CSV 到 XML 是使用 XSLT 2.0 完成的,因此我认为也可以使用它来完成两阶段转换,而不使用节点集函数。

因此,第一阶段是将原始 CSV 文件作为输入,然后输出如上所示的中间 XML。然后获取该中间 XML,并将其传递到另一个转换以获得所需的输出。

任何人都可以帮助如何完成两相转变?我在将第一阶段的输出作为第二阶段的输入传递时遇到问题?

到目前为止我有这样的事情:

<xsl:import href="csv2xml.xsl"/>
<xsl:output method="xml" indent="yes" />

<xsl:variable name="intermediate">
    <xsl:apply-templates select="/" mode="csv2xml"/>
</xsl:variable>

<xsl:template match="rows" name="main">

 **[This is what I'm having trouble with]**

</xsl:template>

I am trying to take a CSV file as input and transform it into a XML. I'm new to XSLT and I've found a way to convert a CSV into XML (using an example from Andrew Welch) like so:

Input CSV file:

car manufacturer,model,color,price,inventory
subaru,outback,blue,23195,54
subaru,forester,silver,20495,23

And my output XML would be:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
   <row>
      <column name="car manufacturer">subaru</column>
      <column name="model">outback</column>
      <column name="color">blue</column>
      <column name="price">23195</column>
      <column name="inventory">54</column>
   </row>
   <row>
      <column name="car manufacturer">subaru</column>
      <column name="model">forester</column>
      <column name="color">silver</column>
      <column name="price">20495</column>
      <column name="inventory">23</column>
   </row>
</rows>

My desired output is actually something similar to:

<stock>
   <model>
      <car>subaru outback</car>
      <color>blue</color>
      <price>23195</price>
      <inventory>54</inventory>
   </model>
   <model>
      <car>subaru forester</car>
      <color>silver</color>
      <price>20495</price>
      <inventory>23</inventory>
   </model>
</stock>

What I read is that it would best be done using a two phase transformation. The CSV to XML is done using XSLT 2.0, so I thought the two phase transformation would be done using that as well without using the node-set function.

So the first phase would be to take the original CSV file as input, and then output the intermediate XML shown above. Then take that intermediate XML, and pass it into another transformation to get the desired output.

Anyone can help on how the two phase transformation can be done? I'm having trouble passing the output of phase one as an input of phase 2?

I have something like this so far:

<xsl:import href="csv2xml.xsl"/>
<xsl:output method="xml" indent="yes" />

<xsl:variable name="intermediate">
    <xsl:apply-templates select="/" mode="csv2xml"/>
</xsl:variable>

<xsl:template match="rows" name="main">

 **[This is what I'm having trouble with]**

</xsl:template>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

默嘫て 2024-11-10 09:52:06

我不明白为什么这种转换需要两个阶段 - 除了可能允许您在其中一个阶段重用现有代码之外。

但是,当您确实需要两个阶段时,一般模型是:

<xsl:template match="/">
  <xsl:variable name="phase-1-result">
    <xsl:apply-templates select="/" mode="phase-1"/>
  </xsl:variable>
  <xsl:apply-templates select="$phase-1-result" mode="phase-2"/>
</xsl:template>

阶段 1 和阶段 2 的模板规则(及其 apply-templates 调用)分别处于阶段 1 或阶段 2 模式。

I don't see any reason why this transformation needs two phases - except perhaps to allow you to reuse existing code for one of the phases.

However, when you do need two phases, the general model is:

<xsl:template match="/">
  <xsl:variable name="phase-1-result">
    <xsl:apply-templates select="/" mode="phase-1"/>
  </xsl:variable>
  <xsl:apply-templates select="$phase-1-result" mode="phase-2"/>
</xsl:template>

with the template rules for phase 1 and phase 2 (and their apply-templates calls) all being in mode phase-1 or phase-2 respectively.

愚人国度 2024-11-10 09:52:06

此 XSLT 2.0 样式表:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="vLines"
         select="tokenize(unparsed-text('test.txt'),'(
)?
')"/>
        <xsl:variable name="vHeaders"
         select="tokenize($vLines[1],',')"/>
        <stock>
            <xsl:for-each select="$vLines[position()!=1]">
                <model>
                    <xsl:variable name="vColumns" select="tokenize(.,',')"/>
                    <xsl:for-each select="$vColumns">
                        <xsl:variable name="vPosition" select="position()"/>
                        <xsl:variable name="vHeader"
                         select="$vHeaders[$vPosition]"/>
                        <xsl:choose>
                            <xsl:when test="$vHeader = 'car manufacturer'">
                                <column name="car">
                                    <xsl:value-of
                                     select="(.,$vColumns[
                                                   index-of($vHeaders,'model')
                                                ])"/>
                                </column>
                            </xsl:when>
                            <xsl:when test="$vHeader = 'model'"/>
                            <xsl:otherwise>
                                <column name="{$vHeader}">
                                    <xsl:value-of select="."/>
                                </column>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each>
                </model>
            </xsl:for-each>
        </stock>
    </xsl:template>
</xsl:stylesheet>

输出:

<stock>
    <model>
        <column name="car">subaru outback</column>
        <column name="color">blue</column>
        <column name="price">23195</column>
        <column name="inventory">54</column>
    </model>
    <model>
        <column name="car">subaru forester</column>
        <column name="color">silver</column>
        <column name="price">20495</column>
        <column name="inventory">23</column>
    </model>
</stock>

注意:在 XSLT 3.0 中,您将能够将模板应用于一般项目。

编辑:正确的名称。

This XSLT 2.0 stylesheet:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="vLines"
         select="tokenize(unparsed-text('test.txt'),'(
)?
')"/>
        <xsl:variable name="vHeaders"
         select="tokenize($vLines[1],',')"/>
        <stock>
            <xsl:for-each select="$vLines[position()!=1]">
                <model>
                    <xsl:variable name="vColumns" select="tokenize(.,',')"/>
                    <xsl:for-each select="$vColumns">
                        <xsl:variable name="vPosition" select="position()"/>
                        <xsl:variable name="vHeader"
                         select="$vHeaders[$vPosition]"/>
                        <xsl:choose>
                            <xsl:when test="$vHeader = 'car manufacturer'">
                                <column name="car">
                                    <xsl:value-of
                                     select="(.,$vColumns[
                                                   index-of($vHeaders,'model')
                                                ])"/>
                                </column>
                            </xsl:when>
                            <xsl:when test="$vHeader = 'model'"/>
                            <xsl:otherwise>
                                <column name="{$vHeader}">
                                    <xsl:value-of select="."/>
                                </column>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each>
                </model>
            </xsl:for-each>
        </stock>
    </xsl:template>
</xsl:stylesheet>

Output:

<stock>
    <model>
        <column name="car">subaru outback</column>
        <column name="color">blue</column>
        <column name="price">23195</column>
        <column name="inventory">54</column>
    </model>
    <model>
        <column name="car">subaru forester</column>
        <column name="color">silver</column>
        <column name="price">20495</column>
        <column name="inventory">23</column>
    </model>
</stock>

Note: In XSLT 3.0 you will be able to apply templates to items in general.

EDIT: Correct names.

一梦等七年七年为一梦 2024-11-10 09:52:06

您可以在此处找到如何使用 XSLT 3.0 执行此操作的示例:

http:// www.stylusstudio.com/tutorials/intro-xslt-3.html

并参见“文本操作”。

You can find here an example of how to do this with XSLT 3.0 :

http://www.stylusstudio.com/tutorials/intro-xslt-3.html

And see under "Text Manipulations".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文