Удалите первый тег ‹p› с помощью XSLT

Я пытаюсь преобразовать стандартный XML QTI для типа вопроса с несколькими вариантами ответов в файл XHTML с помощью XSLT. Я обнаружил трудности с удалением первого тега p из значения тега simpleChoice.

Ниже приведен QTI, который я пытаюсь скрыть в XHTML.

    <?xml version="1.0" encoding="utf-8"?>
<assessmentItem xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 http://www.imsglobal.org/xsd/imsqti_v2p1.xsd" identifier="choice" title="Item Title will come here" adaptive="false" timeDependent="false" xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <responseDeclaration identifier="RESPONSE" cardinality="single" baseType="identifier">
    <correctResponse>
      <value>ChoiceA</value>
    </correctResponse>
  </responseDeclaration>
  <outcomeDeclaration identifier="SCORE" cardinality="single" baseType="integer">
    <defaultValue>
      <value>0</value>
    </defaultValue>
  </outcomeDeclaration>
  <itemBody>
    <div id="item">
      <div id="instruction">Select the correct options</div>
      <choiceInteraction responseIdentifier="RESPONSE" shuffle="false" maxChoices="1">
        <prompt>
            <div id="stem">
                <p>Question will appear here</p>
            </div>
        </prompt>
        <simpleChoice identifier="ChoiceA"><p> answer's first P tag</p> <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</simpleChoice>
        <simpleChoice identifier="ChoiceB"><p> answer's first P tag</p> <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</simpleChoice>
        <simpleChoice identifier="ChoiceC"><p> answer's first P tag</p> <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</simpleChoice>
        <simpleChoice identifier="ChoiceD"><p> answer's first P tag</p> <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</simpleChoice>
        <simpleChoice identifier="ChoiceE"><p> answer's first P tag</p> <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</simpleChoice>
      </choiceInteraction>
    </div>
  </itemBody>
  <responseProcessing template="http://www.imsglobal.org/question/qti_v2p1/rptemplates/match_correct" />
</assessmentItem>

Я смотрю на следующий вывод вариантов

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body>
    <div id="option1">
      <label>A.</label>
      <div class="optionContent">answer's first P tag<p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
    </div>          
    <div id="option2">
      <label>B.</label>
      <div class="optionContent">answer's first P tag<p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
    </div>
    <div id="option3">
      <label>C.</label>
      <div class="optionContent">answer's first P tag<p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
    </div>
    <div id="option4">
      <label>D.</label>
      <div class="optionContent">answer's first P tag<p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
    </div>
    <div id="option5">
      <label>E.</label>
      <div class="optionContent">answer's first P tag<p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
    </div>
  </body>
</html>

Мне нужно удалить первый тег p из тега simpleChoice.

Я пробовал сделать это, используя следующие стили

<xsl:for-each select="//simpleChoice[$vCurrentIndex]/*">
    <xsl:choose>
      <xsl:when test="local-name() = 'p' and position() = 1">
        <xsl:apply-templates select="node()|@*" mode="children" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="{local-name()}">
          <xsl:apply-templates select="node()|@*" mode="children" />
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
</xsl:for-each>

После этого я получаю следующий результат. При выводе не учитываются значения, не входящие в тег P. Получение вывода только для трех тегов P.

<div class="optionContent">answer's second P tag<p> answer's third P tag</p> <p> answer's forth P tag</p></div>

Ваша помощь мне действительно поможет. заранее спасибо


person SMakku    schedule 22.11.2012    source источник


Ответы (2)


Ваш подход к XSLT неверен. Удалите все <xsl:for-each> из всей таблицы стилей. Они вам не нужны и не должны их использовать. Они указывают на то, что вы мыслите процедурно, а XSLT не является процедурным языком.

Эта задача очень проста, если вы используете сопоставление шаблонов вместо for-each. Также используйте правильные объявления пространств имен в своем XSL вместо использования везде local-name().

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:qti="http://www.imsglobal.org/xsd/imsqti_v2p1"
  exclude-result-prefixes="qti"
>
  <xsl:output indent="yes" />

  <xsl:template match="/*">
    <root>
      <xsl:apply-templates select="//qti:simpleChoice" />
    </root>
  </xsl:template>

  <!-- identity template: this is the base of the entire process -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <!-- helper: elements in the qti namespace output their local name -->
  <xsl:template match="qti:*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="node() | @*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="qti:simpleChoice">
    <div id="option{position()}">
      <label>
        <xsl:value-of select="concat(substring(@identifier, 7), '.')" />
      </label>
      <div class="optionContent">
        <xsl:apply-templates />
      </div>  
    </div>
  </xsl:template>

  <!-- the first p in a simpleChoice will just output its contents -->
  <xsl:template match="qti:simpleChoice/qti:p[1]">
    <xsl:apply-templates />
  </xsl:template>

</xsl:stylesheet>

Вывод (см. http://www.xmlplayground.com/IiKDkY)

<root>
  <div id="option1">
    <label>A.</label>
    <div class="optionContent"> answer's first P tag <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
  </div>
  <div id="option2">
    <label>B.</label>
    <div class="optionContent"> answer's first P tag <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
  </div>
  <div id="option3">
    <label>C.</label>
    <div class="optionContent"> answer's first P tag <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
  </div>
  <div id="option4">
    <label>D.</label>
    <div class="optionContent"> answer's first P tag <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
  </div>
  <div id="option5">
    <label>E.</label>
    <div class="optionContent"> answer's first P tag <p> answer's second P tag</p> <p> answer's third P tag</p> <p> answer's forth P tag</p> and text without p tag</div>
  </div>
</root>
person Tomalak    schedule 22.11.2012
comment
Хороший ответ, но в представленной трансформации больше одной ошибки. Вы пробовали его запустить? - person Dimitre Novatchev; 22.11.2012
comment
@Dimitre: Я изменил его после чьего-то комментария (теперь удаленного). В моей первой версии был пустой шаблон (<xsl:template match="qti:simpleChoice/qti:p[1]" />) - это одна исправленная ошибка копирования / вставки. Шаблон работает на xmlplayground (ссылка выше). Я не вижу другую ошибку? - person Tomalak; 22.11.2012
comment
Tomalak, пространство имен xsi не определено. - person Dimitre Novatchev; 22.11.2012
comment
Не лучше ли удалить преобразование идентичности? Мы переходим из пространства имен http://www.imsglobal.org/xsd/imsqti_v2p1 в XHTML. Преобразование идентичности приведет к неправильному пространству имен. - person Thomas W; 23.11.2012
comment
Спасибо Tomalak, это помогло мне решить мою проблему. Я очень ценю ваш быстрый ответ. - person SMakku; 23.11.2012
comment
@ThomasW, На правило идентификации не влияют узлы, принадлежащие пространствам имен, поэтому в этом случае его можно использовать. - person Dimitre Novatchev; 23.11.2012
comment
@DimitreNovatchev Вы правы, пространство имен xsi излишне в exclude-result-prefixes. Не совсем ошибка, но все же ненужная. Я сниму. - person Tomalak; 23.11.2012
comment
@Dimitre Вы правы. Я тестировал его на xmlplayground (который использует PHP и, следовательно, libxml2 внутри), где он работал. Спасибо за подсказку, обратим на это внимание в будущем. - person Tomalak; 23.11.2012
comment
@Tomalak, я никогда не использую игровую площадку или торт - по таким причинам. - person Dimitre Novatchev; 23.11.2012

Мне нужно удалить первый тег p из тега simpleChoice.

Надеюсь, я правильно понял вашу проблему - вы хотите показать первый P как DIV или как SPAN без каких-либо полей и т. Д., Верно?

Тогда я думаю, что лучше использовать содержимое <simpleChoice>...</simpleChoice> как есть. Но в вашем файле CSS для <div class="optionContent"> применить дополнительный стиль для первого тега P. Что-то вроде этого:

.optionContent > p
{
    display: inline;
}
person KoViMa    schedule 22.11.2012
comment
+1 Полагаю, ваш ответ более точен, чем мой. Кажется, что у OP просто проблема с презентацией, а не проблема со структурой. Проблемы с презентацией следует решать с помощью CSS. - person Tomalak; 22.11.2012