xslt 样式表--xml 到 csv:在动态结果文档 (exist-db) 上使用 for-each 循环时出错

xslt stylesheet--xml to csv: error when using for-each loop over dynamic results-document (exist-db)

xslt 新手又来了。作为序言,我会说——就像很多在这里提问的人一样——我来自不同的编程背景,所以我不完全理解 xslt 中的循环,我可能想出了一个扭曲的方法来尝试在这里做我想做的事,如果这一切都被严重误导,我 100% 愿意学习其他更好的方法。

我想做的事情: 遍历 xml 文件的集合并输出 csv 文件。我知道如何一个一个地执行此操作,但我想为一整批文件自动执行此操作。我试图找出在 xslt 中使用集合的方法,但在多次失败尝试后放弃了。

每个 tei/xml 文件都以唯一的三字符代码命名:esmpeople.xml、tdspeople.xml、ldbpeople.xml

我有另一个 tei/xml 文件列出了这些代码:codes.xml

所以我的想法是循环遍历codes.xml,抓取每个代码,然后寻找对应的xml文件,并输出一个csv文件。这是我的代码:

codes.xml

<?xml version="1.0"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml"
    schematypens="http://purl.oclc.org/dsdl/schematron"?><?xml-stylesheet type="text/xsl" href="../xslt/csv-transform-people.xsl"?>
    <TEI xmlns="http://www.tei-c.org/ns/1.0">
    <teiHeader>
        <fileDesc>
            <titleStmt>
                <title/>
            </titleStmt>
            <publicationStmt>
                <p/>
            </publicationStmt>
            <sourceDesc>
<listBibl>
<bibl>
        <note name="workref">OBRAESM</field>
        <note name="workname">Escenas matritenses</field>
        <note name="workauthor">Mesonero Romanos</field>
    </bibl>
    <bibl>
        <note name="workref">OBRATDS</field>
        <note name="workname">Tiempo de silencio</field>
        <note name="workauthor">Luis Martín-Santos</field>
    </bibl>

    <bibl>
        <note name="workref">OBRALDB</field>
        <note name="workname">Luces de Bohemia</field>
        <note name="workauthor">Ramón del Valle-Inclán</field>
    </bibl>
</listBibl>
    </sourceDesc>
        </fileDesc>
        <profileDesc><p/></profileDesc>
    </teiHeader>
    <text>
        <body>
            <p/>
        </body>
    </text>
</TEI>

esmpeople.xml

 <listPerson>
        <person xml:id="PERSSANISIDRO"/>
        <person xml:id="PERSHORACIO"/>
        <person xml:id="PERSBARTOLOMEARGENSOLA"/>
</listPerson>

tdspeople.xml

<listPerson>
        <person xml:id="PERSPEDRO"/>
        <person xml:id="PERSAMADOR"/>
        <person xml:id="PERSRAMONYCAJAL"/>
<listPerson>

ldbpeople.xml

 <listPerson>
        <person xml:id="PERSMAXESTRELLA"/>
        <person xml:id="PERSMADAMACOLLET"/>
        <person xml:id="PERSBUEYAPIS"/>
<listPerson>

csv-转换-people.xsl

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:csv="csv:csv" xmlns:tei="http://www.tei-c.org/ns/1.0" version="1.0">
        <xsl:output omit-xml-declaration="yes" method="text" encoding="utf-8"/>
        <xsl:variable name="separator" select="','"/>
        <xsl:variable name="newline" select="'&#xA;'"/>


        <xsl:template match="/">

         <xsl:for-each select="//tei:listBibl/tei:bibl">

<!--THIS WAS THE PROBLEM-->
        <!--xsl:variable name="workref" select="//tei:note[@name='workref']"/-->

<!--FIX-->
<xsl:variable name="workref" select="tei:note[@name='workref']"/>

        <xsl:variable name="workreflc" select="lower-case($workref)"/>
        <xsl:variable name="workrefshort" select="replace($workref,'OBRA','')"/>
        <xsl:variable name="workrefshortlc" select="lower-case($workrefshort)"/>

        <xsl:variable name="sourcedocuri" select="concat('xmldb:exist://admin:password@00.00.00.00:8080/exist/xmlrpc/db/madrid/xml/',$workrefshortlc,'people.xml')"/>
        <xsl:variable name="sourcedoc" select="doc($sourcedocuri)"/>
        <xsl:variable name="sourcedocperson" select="$sourcedoc//tei:person"/>
            <xsl:result-document href="xmldb:exist://admin:password@00.00.00.00:8080/exist/xmlrpc/db/madrid/csv/people2-{$workreflc}.csv">

                <xsl:text>persref</xsl:text>
                <xsl:value-of select="$separator"/>
                 <xsl:text>persworks</xsl:text>
                <xsl:value-of select="$newline"/>
                <xsl:for-each select="$sourcedocperson">
                    <xsl:variable name="people">
                        <xsl:value-of select="@xml:id"/>
                    </xsl:variable>
                    <xsl:value-of select="$people"/>
                    <xsl:value-of select="$separator"/>

                   <xsl:value-of select="$workref"/>
                    <xsl:value-of select="$newline"/>
                </xsl:for-each>

            </xsl:result-document> </xsl:for-each>
        </xsl:template>

</xsl:stylesheet>

预期结果:三个csv文件存入csv目录:people-obraesm.csv、people-obratds.csv、people-obraldb.csv

我得到的结果: people-obraesm.csv 100% 正确创建,但随后出现此错误:

发生错误:无法将多个结果文档写入同一 URI

所以我能够访问所有 xml 文件并将文件写入 /csv/ 目录,而不会出现权限问题。鉴于错误,我的样式表 and/or 通用逻辑中的循环似乎有问题。真的希望找出我哪里出了问题,因为每当我需要在 xslt 中使用循环时,我都会进入深度试错模式!

答案: 我根据 Martin 的建议更改了上面的 csv-transform-people.xsl,现在可以使用了!

<xsl:for-each select="//tei:listBibl/tei:bibl"> 内部,上下文节点是经过处理的 //tei:listBibl/tei:bibl,因此任何选择都应与其相关,也就是说,您需要 [=13] 而不是 <xsl:variable name="workref" select="//tei:note[@name='workref']"/> =].

附带说明一下,如果使用 XSLT 2 或 3,通常最好在 XSLT 中使用合适的版本(即 version="2.0"version="3.0"),而不是 version="1.0" ,因为这会将 XSLT 处理器置于 XPath 1.0 向后兼容模式。只有将之前由 XSLT 1 处理器处理的 XSLT 1.0 样式表移动到 XSLT 2 或 3 处理器,您才会这样做。