使用 xslt 在两个文件中查找一本书的索引

lookup in two files with xslt for index of a book

我尝试根据 XML 文件用 TeX 设置一本书。我是 XML/XSLT 的新手,无法使 index-output 正常工作:我有一个包含人物姓名的文件和一个包含艺术品标题的文件。

我的source-file:

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

<text>I am a fan of <persName key="A01">Will Shakespeare</persName> and I really do like <workName key="W02">Hamlet</workName>.</text>

结合person.xml:

    <?xml version="1.0" encoding="UTF-8"?>
<root>
    <row>
        <number>A01</number>
        <name>Shakespeare, William</name>
        <born>1564</born>
        <died>1616</died>
    </row>
    <row>
        <number>A02</number>
        <name>Marlowe, Christopher</name>
        <born>1564</born>
        <died>1615</died>
    </row>
</root>

和文件 work.xml

<?xml version="1.0" encoding="UTF-8"?>
<wroot>
    <row>
        <worknumber>W01</worknumber>
        <title>Romeo and Juliet</title>
        <author>A01</author>
    </row>
    <row>
        <worknumber>W02</worknumber>
        <title>Hamlet</title>
        <author>A01</author>
    </row>
</wroot>

并应用此 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:variable name="person-top" select="document('person.xml')/root"/>
    <xsl:variable name="work-top" select="document('work.xml')/wroot"/>
    <xsl:key name="person-lookup" match="row" use="number"/>
    <xsl:key name="work-lookup" match="row" use="worknumber"/>

    <xsl:template match="text">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="persName">
        <xsl:value-of select="."/>
        <xsl:text>\index{</xsl:text>
        <xsl:apply-templates select="$person-top">
            <xsl:with-param name="curr-label" select="."/>
        </xsl:apply-templates>
        <xsl:text>}</xsl:text>
    </xsl:template>

    <xsl:template match="workName">
        <xsl:value-of select="."/>
        <xsl:text>\index{</xsl:text>
        <xsl:apply-templates select="$work-top">
            <xsl:with-param name="curr-label" select="."/>
        </xsl:apply-templates>
        <xsl:text>}</xsl:text>
    </xsl:template>

    <xsl:template match="root">
        <xsl:param name="curr-label"/>
        <xsl:value-of select="key('person-lookup', $curr-label/@key)/name"/>
    </xsl:template>    

    <xsl:template match="wroot">
        <xsl:param name="curr-label"/>
        <xsl:value-of select="key('work-lookup', $curr-label/@key)/title"/>
    </xsl:template>
</xsl:stylesheet>

输出(正确): 我是 Will Shakespeare\index{Shakespeare, William} 的粉丝,我真的很喜欢 Hamlet\index{Hamlet}。

但是要让哈姆雷特在 TeX-index 中作为莎士比亚的 child 出现,我必须实现这种 index-entry 作品:

\index{莎士比亚,威廉!哈姆雷特}

所以在 workName-template 中它应该查找 person-template 并使用 author-key。你能帮我实现吗?

谢谢!马丁

P.S。我想我可以通过将问题分为两步来解决我的问题,第一步是创建一个新的 work2.xml,其中 xslt 填写所有人员的姓名,但这对我来说似乎很乏味且没有必要。

这是一个使用谓词而不是键映射的可能解决方案:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="1.0">

    <xsl:variable name="person-top" select="document('person.xml')/root"/>
    <xsl:variable name="work-top" select="document('work.xml')/wroot"/>

    <xsl:template match="text">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="workName">
        <xsl:value-of select="."/>
        <xsl:variable name="pname" select="../persName/@key" />
        <xsl:variable name="wname" select="@key" />
        <xsl:text>\index{</xsl:text>
        <xsl:value-of select="$person-top/row[number=$pname]/name" />
        <xsl:text>!</xsl:text>
        <xsl:value-of select="$work-top/row[worknumber=$wname]/title"/>
        <xsl:text>}</xsl:text>
    </xsl:template>
</xsl:stylesheet>

它确实从当前 workName-Node 下降一级 (../) 以获得 persName-Node。

我相信这会简单得多 - 如果您确实在使用 XSLT 2.0:

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:param name="persons" select="document('person.xml')"/>
<xsl:param name="works" select="document('work.xml')"/>

<xsl:key name="person-lookup" match="row" use="number"/>
<xsl:key name="work-lookup" match="row" use="worknumber"/>

<xsl:template match="persName">
    <xsl:value-of select="."/>
    <xsl:text>\index{</xsl:text>
    <xsl:value-of select="key('person-lookup', @key, $persons)/name"/>
    <xsl:text>}</xsl:text>
</xsl:template>

<xsl:template match="workName">
    <xsl:variable name="work-entry" select="key('work-lookup', @key, $works)" />
    <xsl:value-of select="."/>
    <xsl:text>\index{</xsl:text>
    <xsl:value-of select="key('person-lookup', $work-entry/author, $persons)/name"/>
    <xsl:text>!</xsl:text>
    <xsl:value-of select="$work-entry/title"/>
    <xsl:text>}</xsl:text>
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,结果将是:

I am a fan of Will Shakespeare\index{Shakespeare, William} and I really do like Hamlet\index{Shakespeare, William!Hamlet}.

注意 key() 函数中第三个参数的使用。