使用XSLT从XML文件生成索引

时间:2019-07-12 13:24:16

标签: xml xslt

我想创建一个字母语料库中提到的人物的索引。

到目前为止,我尚未尝试在XSLT中实现id-Function。但这也许完全是错误的想法。

XML文件(ZL00004.xml和ZL00054.xml)包含persName元素,这些元素使用键属性引用person.xml文件中的人。

ZL00004.xml:

<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" xml:id="ZL00004">
    <teiHeader>
        <fileDesc>
            <titleStmt>
                <title>450</title>
            </titleStmt>
        </fileDesc>
        <profileDesc>
            <correspDesc>
                <correspAction type="sent">
                    <persName key="ZP00002">Hugo Grotius</persName>
                </correspAction>
                <correspAction type="received">
                    <persName key="ZP00001">Justus Scaliger</persName>
                </correspAction>
            </correspDesc>
        </profileDesc>
    </teiHeader>
    <text type='letter' xml:lang="en">
    <body>
        <div>
            <opener>
                <salute>My dear <persName key="ZP00001">Justus</persName>,</salute>
            </opener>
            <p>Some text that mentions <persName key="ZP00003">Isaac </persName></p>
            <closer>Best regards, 
                <lb></lb>
                <signed><persName key="ZP00002">Hugo</persName></signed>
            </closer>
        </div>
    </body>
</text>
</TEI>

ZL00054.xml:

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

<TEI xmlns="http://www.tei-c.org/ns/1.0" xml:id="ZL00054">
    <teiHeader>
        <fileDesc>
            <titleStmt>
                <title>800</title>
            </titleStmt>
        </fileDesc>
        <profileDesc>
            <correspDesc>
                <correspAction type="sent">
                    <persName key="ZP00001">Justus Scaliger</persName>
                </correspAction>
                <correspAction type="received">
                    <persName key="ZP00002">Hugo Grotius</persName>
                </correspAction>
            </correspDesc>
        </profileDesc>
    </teiHeader>
    <text type='letter' xml:lang="en">
        <body>
            <div>
                <opener>
                    <salute>My dear <persName key="ZP00002">Hugo</persName>,</salute>
                </opener>
                <p>Some text that mentions <persName key="ZP00003">Isaac</persName> and <persName key="ZP00002">Hugo</persName>.</p>
                <closer>Best regards, 
                    <lb></lb>
                    <signed><persName key="ZP00001">Justus</persName></signed>
                </closer>
            </div>
        </body>
    </text>
</TEI>

persons.xml:

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

<Persons>
<person xml:id="ZP00001">
    <persName><forename>Joseph Justus</forename><surname>Scaliger</surname></persName>
</person>

<person xml:id="ZP00002">
    <persName><forename>Hugo</forename><surname>Grotius</surname></persName>
</person>

    <person xml:id="ZP00003">
        <persName><forename>Isaac</forename><surname>Casaubon</surname></persName>
    </person>
</Persons>

目标是创建一个索引,其中每个人的条目均引用相应字母(标题元素)的编号。这些人按字母顺序排列。该索引根据其功能引用每个。 Grotius信件中提及的人归为“ mentHG” –其他发件人提及的人归为“ mentO”:

  • 卡绍邦在信中提到。 450由Grotius-用“ mentHG”表示。因为只有斯卡利格(Scaliger)在信中提到他。 800,这是强调。
  • 格罗蒂乌斯(Grotius)被指示为信件编号的发件人。 450和否的接收者。 800.他的编号在第。 Scaliger并不强调800。
  • Scaliger被指示为信件编号的发件人。 800和否的接收者。 450。

输出应如下所示:

艾萨克州卡绍邦

  • mentHG 450,(以及更多字母)
  • mentO 800,(以及更多字母)

格劳修斯·雨果

  • 发件人 450,(以及更多字母)
  • 地址 800,(以及更多字母)
  • mentO 800,(以及更多字母)

Scaliger,Justus

  • 地址 450,(以及更多字母)
  • 发件人 800,(以及更多字母)

这是我所得到的代码的全部信息

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://www.tei-c.org/ns/1.0">
  <xsl:output method="text" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="/">

    <xsl:for-each
      select="document(/library/document/@filename)/tei:TEI">
      <xsl:apply-templates select="."/>
    </xsl:for-each>

  </xsl:template>
  <xsl:template match="tei:TEI">

    <xsl:for-each select="Persons/person">
      <xsl:text>&#xA; </xsl:text>
      <xsl:value-of select="name"/>
      <xsl:text> (ID </xsl:text>
      <xsl:value-of select="@xml:id"/>
      <xsl:text>) is found in these letters:&#xA;</xsl:text> 
      <xsl:value-of select="//@xml:id[idref(@xml:id)]" 
        separator="&#xA;"/>
      <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each>

  </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:0)

这是我在注释链接中使用键和XSLT 2/3的建议,仅适用于不插入字母,而是像使用文档功能在示例中一样加载它们:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tei="http://www.tei-c.org/ns/1.0"
    expand-text="yes"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="letters" select="document(/library/document/@filename)"/>

  <xsl:key name="sender" 
    match="tei:TEI" 
    use="tei:teiHeader/tei:profileDesc/tei:correspDesc/tei:correspAction[@type = 'sent']/tei:persName/@key"/>

  <xsl:key name="adressee" 
    match="tei:TEI" 
    use="tei:teiHeader/tei:profileDesc/tei:correspDesc/tei:correspAction[@type = 'received']/tei:persName/@key"/>

  <xsl:key name="letter-ref" match="tei:TEI" use="tei:text//tei:persName/@key"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>.NET XSLT Fiddle Example</title>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:variable name="grotius-letters" select="key('sender', 'ZP00002', $letters)"/>
  <xsl:variable name="others-letters" select="$letters/tei:TEI except $grotius-letters"/>

  <xsl:template match="Persons">
      <xsl:where-populated>
          <ol>
              <xsl:apply-templates select="person">
                  <xsl:sort select="persName/surname"/>
                  <xsl:sort select="persName/forename"/>
              </xsl:apply-templates>
          </ol>
      </xsl:where-populated>
  </xsl:template>

  <xsl:template match="person">
      <li>
          <b>{persName/surname}, {persName/forename}</b>
          <xsl:variable name="letters-sent" select="key('sender', @xml:id, $letters)"/>
          <xsl:variable name="letters-received" select="key('adressee', @xml:id, $letters)"/>
          <xsl:variable name="mentioned-grotius" select="key('letter-ref', @xml:id, $grotius-letters)"/>
          <xsl:variable name="mentioned-others" select="key('letter-ref', @xml:id, $others-letters)"/>
          <xsl:where-populated>
              <ul>
                  <xsl:apply-templates select="$letters-sent" mode="ref-item">
                      <xsl:with-param name="ref-type" select="'Sender'"/>
                  </xsl:apply-templates>
                  <xsl:apply-templates select="$letters-received" mode="ref-item">
                      <xsl:with-param name="ref-type" select="'Adressee'"/>
                  </xsl:apply-templates>
                  <xsl:apply-templates select="$mentioned-grotius" mode="ref-item">
                      <xsl:with-param name="ref-type" select="'mentHG'"/>
                  </xsl:apply-templates>
                  <xsl:apply-templates select="$mentioned-others" mode="ref-item">
                      <xsl:with-param name="ref-type" select="'mentO'"/>
                  </xsl:apply-templates>
              </ul>
          </xsl:where-populated>
      </li>
  </xsl:template>

  <xsl:template match="tei:TEI" mode="ref-item">
      <xsl:param name="ref-type"/>
      <li><em>{$ref-type}</em> {tei:teiHeader/tei:fileDesc/tei:titleStmt/tei:title}</li>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bnnZWY/2

它并没有您在问题中显示的输出,但是正如您在评论中所说的那样,“正是我要实现的目标”,我希望您可以根据需要对其进行调整,以排除一些参考。

该代码使用了Saxon 9.8和更高版本中提供的XSLT 3,但是当然,仅使用XSLT 3的某些功能(例如文本值模板和xsl:mode声明)就可以在XSLT 2中通过使用{ {1}}和用于身份转换的详细模板。