使用 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()
函数中第三个参数的使用。
我尝试根据 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()
函数中第三个参数的使用。