Как перечислить проиндексированные (xsl: key) элементы? - PullRequest
2 голосов
/ 29 июня 2009

Я новичок в XML, извините за глупый вопрос. Я пытаюсь создать шаблон xsl для преобразования исходного XML в пункт назначения. На самом деле это почти сделано, но я не знаю, как правильно перечислить <creator> (создатель @ affil в Destination xml).

Источник:

<?xml version="1.0" encoding="iso-8859-1"?>
<CREATORS>
  <PERSON ROLE="CONTACT">
    <PREFIX>Prof</PREFIX>
    <FIRST_NAME>Mike</FIRST_NAME>
    <MIDDLE_INITIALS>J</MIDDLE_INITIALS>
    <LAST_NAME>Petrov</LAST_NAME>
    <SUFFIX/>
    <POSITION>Director</POSITION>
    <EMAIL_1>pontorez@pontorez.ru</EMAIL_1>
    <EMAIL_2>webmaster@pontorez.ru</EMAIL_2>
    <URL>www.pontorez.ru</URL>
    <MOBILE_PHONE/>
    <ADDRESS>
      <DEPARTMENT/>
      <ORGANISATION>Example</ORGANISATION>
      <ADDRESS_1>Finch Pavilion</ADDRESS_1>
      <ADDRESS_2>Middle Way</ADDRESS_2>
      <CITY>Oxford</CITY>
      <ZIP>OX9 7LG</ZIP>
      <REGION/>
      <COUNTRY CODE="GB">UK</COUNTRY>
      <PHONE_1>+380 6245 716300</PHONE_1>
      <PHONE_2/>
      <FAX_1>+380 6245 716311</FAX_1>
      <FAX_2/>
    </ADDRESS>
    <FOOTNOTE/>
  </PERSON>
  <PERSON ID="7091" ROLE="AUTHOR">
    <PREFIX>Prof</PREFIX>
    <FIRST_NAME>Mike</FIRST_NAME>
    <MIDDLE_INITIALS>J</MIDDLE_INITIALS>
    <LAST_NAME>Petrov</LAST_NAME>
    <SUFFIX/>
    <POSITION>Director</POSITION>
    <EMAIL_1>pontorez@pontorez.ru</EMAIL_1>
    <EMAIL_2>webmaster@pontorez.ru</EMAIL_2>
    <URL>www.pontorez.ru</URL>
    <MOBILE_PHONE/>
    <ADDRESS>
      <DEPARTMENT/>
      <ORGANISATION>Example</ORGANISATION>
      <ADDRESS_1>Finch Pavilion</ADDRESS_1>
      <ADDRESS_2>Middle Way</ADDRESS_2>
      <CITY>Oxford</CITY>
      <ZIP>OX9 7LG</ZIP>
      <REGION/>
      <COUNTRY CODE="GB">UK</COUNTRY>
      <PHONE_1>+380 6245 716300</PHONE_1>
      <PHONE_2/>
      <FAX_1>+380 6245 716311</FAX_1>
      <FAX_2/>
    </ADDRESS>
    <FOOTNOTE>Author footnote</FOOTNOTE>
  </PERSON>
  <PERSON ID="7094" ROLE="AUTHOR">
    <PREFIX>Mrs</PREFIX>
    <FIRST_NAME>Anne</FIRST_NAME>
    <MIDDLE_INITIALS/>
    <LAST_NAME>Spencer</LAST_NAME>
    <SUFFIX/>
    <POSITION/>
    <EMAIL_1>aspencer@Hardware.co.uk</EMAIL_1>
    <EMAIL_2/>
    <URL/>
    <MOBILE_PHONE/>
    <ADDRESS>
      <DEPARTMENT/>
      <ORGANISATION>Example</ORGANISATION>
      <ADDRESS_1>SEO R&amp;D Programme</ADDRESS_1>
      <ADDRESS_2>Finch Pavilion, Middle Way</ADDRESS_2>
      <CITY>Oxford</CITY>
      <ZIP>OX9 7LG</ZIP>
      <REGION>Oxfordshire</REGION>
      <COUNTRY CODE="GB">UK</COUNTRY>
      <PHONE_1>+380 6245 716300</PHONE_1>
      <PHONE_2/>
      <FAX_1>+380 6245 716311</FAX_1>
      <FAX_2/>
    </ADDRESS>
    <FOOTNOTE/>
  </PERSON>
  <PERSON ID="15756" ROLE="AUTHOR">
    <PREFIX>Mr</PREFIX>
    <FIRST_NAME>Ed</FIRST_NAME>
    <MIDDLE_INITIALS/>
    <LAST_NAME>Gantos</LAST_NAME>
    <SUFFIX/>
    <POSITION>Senior Medical Statistician</POSITION>
    <EMAIL_1>santos@xxx.org.uk</EMAIL_1>
    <EMAIL_2/>
    <URL>http://www.isds.sxo.ac.uk/</URL>
    <MOBILE_PHONE/>
    <ADDRESS>
      <DEPARTMENT>Head of SEO Support</DEPARTMENT>
      <ORGANISATION>Centre for Statistics in Software</ORGANISATION>
      <ADDRESS_1>Pearson College</ADDRESS_1>
      <ADDRESS_2>Linton Road</ADDRESS_2>
      <CITY>Oxford</CITY>
      <ZIP>OX9 6UD</ZIP>
      <REGION/>
      <COUNTRY CODE="GB">UK</COUNTRY>
      <PHONE_1>+380 6245 112404</PHONE_1>
      <PHONE_2/>
      <FAX_1>+380 6245 112424</FAX_1>
      <FAX_2/>
    </ADDRESS>
    <FOOTNOTE/>
  </PERSON>
  <PERSON ID="7092" ROLE="AUTHOR">
    <PREFIX>Dr</PREFIX>
    <FIRST_NAME>Sherry</FIRST_NAME>
    <MIDDLE_INITIALS/>
    <LAST_NAME>Wilson</LAST_NAME>
    <SUFFIX/>
    <POSITION/>
    <EMAIL_1>wilson@Hardware.co.uk</EMAIL_1>
    <EMAIL_2/>
    <URL/>
    <MOBILE_PHONE/>
    <ADDRESS>
      <DEPARTMENT/>
      <ORGANISATION>Example</ORGANISATION>
      <ADDRESS_1>SEO R&amp;D Programme</ADDRESS_1>
      <ADDRESS_2>Finch Pavilion, Middle Way</ADDRESS_2>
      <CITY>Oxford</CITY>
      <ZIP>OX9 7LG</ZIP>
      <REGION>Oxfordshire</REGION>
      <COUNTRY CODE="GB">UK</COUNTRY>
      <PHONE_1>+380 6245 716300</PHONE_1>
      <PHONE_2/>
      <FAX_1>+380 6245 716311</FAX_1>
      <FAX_2/>
    </ADDRESS>
    <FOOTNOTE/>
  </PERSON>
  <GROUP ID="????">
    <GROUP_NAME>Bond team</GROUP_NAME>
    <CONTACT_PERSON>Monica Bond</CONTACT_PERSON>
    <EMAIL_1>mk@Hardware.dk</EMAIL_1>
    <URL/>
    <ADDRESS>
      <DEPARTMENT>Nordic Hardware Centre</DEPARTMENT>
      <ORGANISATION>Creyts, Dept 7512</ORGANISATION>
      <ADDRESS_1>Blegdamsvej 219</ADDRESS_1>
      <ADDRESS_2/>
      <CITY>Copenhagen</CITY>
      <ZIP>2900</ZIP>
      <REGION/>
      <COUNTRY CODE="DK">Denmark</COUNTRY>
      <PHONE_1>+415 7667 7110</PHONE_1>
      <PHONE_2>+415 1234 9429</PHONE_2>
      <FAX_1>+415 7667 7007</FAX_1>
      <FAX_2/>
    </ADDRESS>
    <FOOTNOTE>Group footnote</FOOTNOTE>
  </GROUP>
  <PERSON ID="3" ROLE="AUTHOR">
    <PREFIX>Ms</PREFIX>
    <FIRST_NAME>Monica</FIRST_NAME>
    <MIDDLE_INITIALS/>
    <LAST_NAME>Bond</LAST_NAME>
    <SUFFIX/>
    <POSITION>Director of the Hardware Information Management System</POSITION>
    <EMAIL_1>mk@Hardware.dk</EMAIL_1>
    <EMAIL_2/>
    <URL>www.cc-ims.net</URL>
    <MOBILE_PHONE/>
    <ADDRESS>
      <DEPARTMENT>Nordic Hardware Centre</DEPARTMENT>
      <ORGANISATION>Creyts, Dept 7512</ORGANISATION>
      <ADDRESS_1>Blegdamsvej 219</ADDRESS_1>
      <ADDRESS_2/>
      <CITY>Copenhagen</CITY>
      <ZIP>2900</ZIP>
      <REGION/>
      <COUNTRY CODE="DK">Denmark</COUNTRY>
      <PHONE_1>+415 7667 7110</PHONE_1>
      <PHONE_2>+415 1234 9429</PHONE_2>
      <FAX_1>+415 7667 7007</FAX_1>
      <FAX_2/>
    </ADDRESS>
    <FOOTNOTE/>
  </PERSON>
</CREATORS>

Назначение:

<?xml version="1.0" encoding="utf-8"?>
<creatorGroup>
  <creator affil="CD004002-aff-0001" creatorRole="author">
    <forenames>Mike</forenames>
    <surnamePrefix>J</surnamePrefix>
    <surname>Petrov</surname>
    <note id="CD004002-note-0001">
      <p>Author footnote</p>
    </note>
  </creator>
  <creator affil="CD004002-aff-0001" creatorRole="author">
    <forenames>Anne</forenames>
    <surname>Spencer</surname>
  </creator>
  <creator affil="CD004002-aff-0002" creatorRole="author">
    <forenames>Ed</forenames>
    <surname>Gantos</surname>
  </creator>
  <creator affil="CD004002-aff-0001" creatorRole="author">
    <forenames>Sherry</forenames>
    <surname>Wilson</surname>
  </creator>
  <creator affil="CD004002-aff-0003" type="collaboration" creatorRole="author">
    <collab>Bond team</collab>
  </creator>
  <creator affil="CD004002-aff-0003" creatorRole="author">
    <forenames>Monica</forenames>
    <surname>Bond</surname>
  </creator>
  <creator affil="CD004002-aff-0001" creatorRole="contact">
    <honorifics>Prof</honorifics>
    <forenames>Mike</forenames>
    <surnamePrefix>J</surnamePrefix>
    <surname>Petrov</surname>
    <jobTitle>Director</jobTitle>
    <email>pontorez@pontorez.ru</email>
    <email>webmaster@pontorez.ru</email>
  </creator>
  <affiliation id="CD004002-aff-0001" countryCode="GB">
    <orgName>Example</orgName>
    <address>
      <street>Finch Pavilion</street>
      <street>Middle Way</street>
      <city>Oxford</city>
      <country>UK</country>
      <postCode>OX9 7LG</postCode>
    </address>
  </affiliation>
  <affiliation id="CD004002-aff-0002" countryCode="GB">
    <orgName>Centre for Statistics in Software</orgName>
    <orgDiv>Head of SEO Support</orgDiv>
    <address>
      <street>Pearson College</street>
      <street>Linton Road</street>
      <city>Oxford</city>
      <country>UK</country>
      <postCode>OX9 6UD</postCode>
    </address>
  </affiliation>
  <affiliation id="CD004002-aff-0003" countryCode="DK">
    <collabContact>Monica Bond</collabContact>
    <orgName>Creyts, Dept 7512</orgName>
    <orgDiv>Nordic Hardware Centre</orgDiv>
    <address>
      <street>Blegdamsvej 219</street>
      <city>Copenhagen</city>
      <country>Denmark</country>
      <postCode>2900</postCode>
    </address>
  </affiliation>
</creatorGroup>

Созданная мной таблица стилей XSL:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="affiliations" match="ORGANISATION" use="."/>

  <xsl:template name="kreator">
    <xsl:variable name="affid">
      <!-- The numbering problem is in the below line: -->
      <xsl:number format="0001" value="position()"/>
    </xsl:variable>

    <xsl:variable name="role">
      <xsl:choose>
        <xsl:when test="@ROLE='AUTHOR' or name()='GROUP'">author</xsl:when>
        <xsl:otherwise>contact</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <creator affil="CD004002-aff-{$affid}">
      <xsl:if test="GROUP_NAME!=''">
        <xsl:attribute name="type">collaboration</xsl:attribute>
      </xsl:if>
      <xsl:attribute name="creatorRole">
        <xsl:value-of select="$role"/>
      </xsl:attribute>
      <xsl:if test="$role='contact'">
        <honorifics>
          <xsl:value-of select="PREFIX"/>
        </honorifics>
      </xsl:if>
      <xsl:if test="GROUP_NAME!=''">
        <collab>
          <xsl:value-of select="GROUP_NAME"/>
        </collab>
      </xsl:if>
      <xsl:if test="FIRST_NAME">
        <forenames>
          <xsl:value-of select="FIRST_NAME"/>
        </forenames>
      </xsl:if>
      <xsl:if test="MIDDLE_INITIALS!=''">
        <surnamePrefix>
          <xsl:value-of select="MIDDLE_INITIALS"/>
        </surnamePrefix>
      </xsl:if>
      <xsl:if test="LAST_NAME">
        <surname>
          <xsl:value-of select="LAST_NAME"/>
        </surname>
      </xsl:if>
      <xsl:if test="FOOTNOTE!='' and name()='PERSON'">
        <note id="CD004002-note-{$affid}">
          <p>
            <xsl:value-of select="FOOTNOTE"/>
          </p>
        </note>
      </xsl:if>
      <xsl:if test="$role='contact'">
        <jobTitle><xsl:value-of select="POSITION"/></jobTitle>
        <email><xsl:value-of select="EMAIL_1"/></email>
        <email><xsl:value-of select="EMAIL_2"/></email>
      </xsl:if>

    </creator>
    <xsl:text>&#xA;&#xA;</xsl:text>

  </xsl:template>

  <xsl:template match="/CREATORS">
    <xmp>
      <creatorGroup>
        <!-- list of creators: -->
        <xsl:for-each select="PERSON[@ROLE='AUTHOR'] | GROUP">
          <xsl:call-template name="kreator"/>
        </xsl:for-each>
        <xsl:for-each select="PERSON[@ROLE='CONTACT']">
          <xsl:call-template name="kreator"/>
        </xsl:for-each>
        <!-- list of affiliations: -->
        <xsl:for-each select="//ORGANISATION[generate-id(.)=generate-id(key('affiliations', .))]">
          <affiliation>
            <xsl:attribute name="id">
              CD004002-aff-000<xsl:value-of select="position()"/>
            </xsl:attribute>
            <xsl:attribute name="countryCode">
              <xsl:value-of select="../COUNTRY/@CODE"/>
            </xsl:attribute>
            <xsl:if test="../../CONTACT_PERSON">
              <collabContact>
                <xsl:value-of select="../../CONTACT_PERSON"/>
              </collabContact>
            </xsl:if>
            <orgName>
              <xsl:value-of select="."/>
            </orgName>
            <xsl:if test="../DEPARTMENT!=''">
              <orgDiv>
                <xsl:value-of select="../DEPARTMENT"/>
              </orgDiv>
            </xsl:if>
            <address>
              <street>
                <xsl:value-of select="../ADDRESS_1"/>
              </street>
              <xsl:if test="../ADDRESS_2!=''">
                <street>
                  <xsl:value-of select="../ADDRESS_2"/>
                </street>
              </xsl:if>

              <city>
                <xsl:value-of select="../CITY"/>
              </city>
              <country>
                <xsl:value-of select="../COUNTRY"/>
              </country>
              <postCode>
                <xsl:value-of select="../ZIP"/>
              </postCode>
            </address>
          </affiliation>
          <xsl:text>&#xA;&#xA;</xsl:text>
        </xsl:for-each>
      </creatorGroup>
    </xmp>
  </xsl:template>

</xsl:stylesheet>

т.е. Я хочу получить <creator> нумерацию, как показано ниже:

<creator affil="CD004002-aff-0001" creatorRole="author"/>
<creator affil="CD004002-aff-0001" creatorRole="author"/>
<creator affil="CD004002-aff-0002" creatorRole="author"/>
<creator affil="CD004002-aff-0001" creatorRole="author"/>
<creator affil="CD004002-aff-0003" type="collaboration" creatorRole="author"/>
<creator affil="CD004002-aff-0003" creatorRole="author"/>
<creator affil="CD004002-aff-0001" creatorRole="contact"/>

Хотя моя текущая таблица стилей XSL выдает неправильные @ affil's:

<creator affil="CD004002-aff-0004" creatorRole="author"/>
<creator affil="CD004002-aff-0004" creatorRole="author"/>
<creator affil="CD004002-aff-0001" creatorRole="author"/>
<creator affil="CD004002-aff-0004" creatorRole="author"/>
<creator affil="CD004002-aff-0002" type="collaboration" creatorRole="author"/>
<creator affil="CD004002-aff-0002" creatorRole="author"/>
<creator affil="CD004002-aff-0004" creatorRole="contact"/>

Можете ли вы помочь, пожалуйста? Благодаря.

1 Ответ

2 голосов
/ 30 июня 2009

Ваша проблема в том, что когда вы делаете:

<xsl:call-template name="kreator" />

, тогда вы делаете это в контексте <PERSON> или <GROUP>, с которым вы сейчас работаете.

Это означает, что position() сообщит вам позицию этих элементов . Он не может волшебным образом знать, что вас интересует положение первого <ORGANISATION>, совпадающего с текущим.

И это означает, что вы должны выполнить итерацию всех <ORGANISATION> почти так же, как вы делаете это для вычисления атрибута <affiliation> @id:

<xsl:variable name="affid">
  <xsl:variable name="org" select="ADDRESS/ORGANISATION" />
  <xsl:for-each select="//ORGANISATION[
    generate-id()
    =
    generate-id(key('affiliations', .)[1])
  ]">
    <xsl:if test=". = $org">
      <xsl:number format="0001" value="position()"/>
    </xsl:if>
  </xsl:for-each>
</xsl:variable>

Обратите внимание на использование <xsl:if>, чтобы убедиться, что переменная в конечном итоге содержит только одно значение, даже если вы просматриваете все из них.

Для больших документов вы можете ввести другой ключ:

<xsl:key name="organisations" match="ORGANISATION" use="'all'" />

и использовать это как замену для всех сравнительно неэффективных выражений "//ORGANISATION", например, вместо:

<xsl:for-each select="//ORGANISATION">
  <!-- ... -->
</xsl:for-each>

использование:

<xsl:for-each select="key('organisations', 'all')">
  <!-- ... -->
</xsl:for-each>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...