How to access previous and next item based on a condition

╄→尐↘猪︶ㄣ 提交于 2020-01-25 08:34:06

问题


I have 2000 TEI-XML-files with letters between different people and a single person in a single folder. I can access the previous and next letter chronologically as the filename starts with the date of the sender (e.g. 2001-02-21.xml). But what I want to achieve is to create an XSLT (2 or 3, doesn't matter) that writes the next letter to or from the specific writer/receiver into the xml-file.

Say I have this:

 <correspDesc>
 <correspAction type="sent">
  <persName key="CMvW">Carl Maria von Weber</persName>
  <settlement>Dresden</settlement>
  <date when="1817-06-23">23 June 1817</date>
 </correspAction>
 <correspAction type="received">
  <persName key="CB">Caroline Brandt</persName>
  <settlement>Prag</settlement>
 </correspAction>
    </correspDesc>

and i want to add this field as a third child after correspAction:

     <correspContext>
      <ref type="prev"
       target="http://www.weber-gesamtausgabe.de/A041209">Previous letter of
      <persName key="CMvW">Carl Maria von Weber</persName> 
         to <persName key="CB">Caroline Brandt</persName>:
      <date from="1817-06-19" to="1817-06-20">June 19/20, 1817</date>
      </ref>
      <ref type="next"
       target="http://www.weber-gesamtausgabe.de/A041217">Next letter of
      <persName key="CMvW">Carl Maria von Weber</persName> to
      <persName key="CB">Caroline Brandt</persName>:
      <date when="1817-06-27">June 27, 1817</date>
      </ref>
     </correspContext>

how would I do it? In the example Caroline Brandt is the changing sender/receiver. So basically I would need a collection of all XML-files with //correspDesc//persName[@key='CB'] and in each file access the preceding and following one of the collection. How can I achieve that?

begin of the solution

@martin-honnen pointed me the way though I'm certain it is not the most elegant way.

1) I've used collection to copy all correspDesc into one file. I add an attribute 'lookup' with the key of the person and the date the letter was sent combined and an attribute with just 'person' to identify the letters of a correspondence.

   <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
    <xsl:mode on-no-match="shallow-copy"/>
    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="false"/>

    <xsl:template match="/">
        <xsl:element name="root">
            <xsl:for-each select="collection('?select=*.xml;recurse=no')">
                <xsl:element name="correspDesc">
                    <xsl:attribute name="lookup">
                        <xsl:choose>
                            <xsl:when test="//correspAction[@type='sent']/persName/@key='pmb2121'">
                                <xsl:value-of select="//correspAction[@type='received']/persName/@key"/>
                                <xsl:text>|</xsl:text>
                                <xsl:value-of select="//correspAction[@type='sent']/date/@when"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="//correspAction[@type='sent']/persName/@key"/>
                                <xsl:text>|</xsl:text>
                                <xsl:value-of select="//correspAction[@type='sent']/date/@when"/>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:attribute>
                    <xsl:attribute name="person">
                        <xsl:choose>
                            <xsl:when test="//correspAction[@type='sent']/persName/@key='pmb2121'">
                                <xsl:value-of select="//correspAction[@type='received']/persName/@key"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="//correspAction[@type='sent']/persName/@key"/>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:attribute>
                    <xsl:apply-templates select="//correspAction"/>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

2) I order the resulting list using the date-field

 <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">

    <xsl:mode on-no-match="shallow-copy" />
    <xsl:output indent="yes"
        method="xml"
        encoding="utf-8"
        omit-xml-declaration="false"/>

    <xsl:template match="root">
        <xsl:element name="root">
            <xsl:apply-templates select="correspDesc">
                <xsl:sort select="correspAction[@type='sent']/date/@when" data-type="text" order="ascending"/>
            </xsl:apply-templates>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Now my next task is to use param and key to lookup the preceding and following entries.

    <xsl:param name="correspList" select="document('correspList.xml')"/>
    <xsl:key name="corresp-lookup" match="@lookup"/>
    <xsl:key name="correspPerson-lookup" match="@person"/>

I am not sure how I will achieve that but I will update here once I have that code.

来源:https://stackoverflow.com/questions/58977093/how-to-access-previous-and-next-item-based-on-a-condition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!