XSLT 1.0 - Как определить совпадение шаблона с предложением теста, чтобы сравнить его со значением параметра - PullRequest
1 голос
/ 27 октября 2011

Ну, я не могу решить эту проблему викторины XSLT 1.0. Вот исходный XML ...

<College>

    <Class>
        <History>
            <StudentName>Veronica</StudentName>
        </History>
    </Class>

    <Class>
        <History>
            <StudentName>Jasmine</StudentName>
        </History>
    </Class>

    <Class>
        <History>
            <StudentName>Rebecca</StudentName>
        </History>
    </Class>

</College>

Я пытаюсь придумать XSLT 1.0, чтобы добавить новый элемент «AddThis» в третий узел «History», используя параметр, чтобы указать, какому узлу «History» добавить «AddThis», как показано ниже ...

<College>

    <Class>
        <History>
            <StudentName>Veronica</StudentName>
        </History>
    </Class>

    <Class>
        <History>
            <StudentName>Jasmine</StudentName>
        </History>
    </Class>

    <Class>
        <History>
            <StudentName>Rebecca</StudentName>
            <AddThis>Ok</AddThis>
        </History>
    </Class>

</College>

Большое спасибо, что нашли время прочитать этот вопрос.

РЕДАКТИРОВАТЬ: мне пришлось исправить местоположение нового элемента "AddThis" внутри узла "History", а не за пределами узла "History", извините.

Ответы [ 2 ]

1 голос
/ 27 октября 2011

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pNum" select="3"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Class[History]">
  <xsl:choose>
   <xsl:when test="not(position() = $pNum)">
     <xsl:call-template name="identity"/>
   </xsl:when>
   <xsl:otherwise>
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
      <AddThis>Ok</AddThis>
    </xsl:copy>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<College>
    <Class>
        <History>
            <StudentName>Veronica</StudentName>
        </History>
    </Class>
    <Class>
        <History>
            <StudentName>Jasmine</StudentName>
        </History>
    </Class>
    <Class>
        <History>
            <StudentName>Rebecca</StudentName>
        </History>
    </Class>
</College>

дает желаемый, правильный результат :

<College>
   <Class>
      <History>
         <StudentName>Veronica</StudentName>
      </History>
   </Class>
   <Class>
      <History>
         <StudentName>Jasmine</StudentName>
      </History>
   </Class>
   <Class>
      <History>
         <StudentName>Rebecca</StudentName>
      </History>
      <AddThis>Ok</AddThis>
   </Class>
</College>

Объяснение : Очень типичное переопределение правила идентификации.

Решение XSLT 2.0 :

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pNum" select="3"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Class[History][position() = $pNum]">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
      <AddThis>Ok</AddThis>
    </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

Объяснение : Почти то же самое, что и решение XSLT 1.0, но короче, потому что в XSLT 2.0 допустимо, чтобы ссылка на переменную / параметр встречалась в шаблоне соответствия - поэтому мы полностью избавляемся явные условия.

Обновление : ОП теперь изменил проблему:

" извините, элемент" AddThis "должен был быть добавлен внутри третий узел «История», не выходящий за пределы третьего узла «История», мой плохой. я исправил это в моем посте с вопросом. Как бы я отредактировал ваш XSLT 1.0 в исправить это? Благодарю. - Bug Spray"

Вот соответственно измененное решение :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pNum" select="3"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Class[History]">
  <xsl:choose>
   <xsl:when test="not(position() = $pNum)">
     <xsl:call-template name="identity"/>
   </xsl:when>
   <xsl:otherwise>
    <xsl:apply-templates select="." mode="add"/>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="node()|@*" mode="add" name="id2">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*" mode="add"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="History/StudentName" mode="add">
  <xsl:call-template name="id2"/>
  <AddThis>Ok</AddThis>
 </xsl:template>
</xsl:stylesheet>
1 голос
/ 27 октября 2011

Ваше условие никогда не выполняется, потому что preceding-sibling:: делает то, что говорит на жестяной коробке: он выбирает предшествующие родственные узлы.Из которых не будет ничего в вашей структуре XML для элементов History!Таким образом, ваш тестовый атрибут всегда будет давать выражение, эквивалентное: test="(0 +1) = 3", то есть test="false()".

Вам необходимо либо переосмыслить ваш селектор XPath, т.е. вам нужно выбрать узлы preceding-sibling:: на узле parent::; или вам необходимо реструктурировать свой XSLT, чтобы поток сопоставления с шаблоном автоматически правильно выбирал узлы.(Что-то вроде match="Class[(position() +1)= $position]" для выбора 4-й позиции в вашем примере.)

Кроме того, ваша логика странная: индексы / позиции XSLT основаны на 1, а не на 0, как в большинстве языков.Поэтому кажется более понятным выбрать 4-й элемент, изменив предложение $position param, а не добавив его в подвыражение вашего предиката.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...