Условное изменение текста у нескольких детей с одинаковыми именами - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь условно изменить содержимое некоторого XML.У элемента есть несколько детей с одинаковыми именами, которые я хочу изменить в зависимости от содержимого текста.Например, у меня есть следующий XML:

<first>
  <second>
    <third>alice</third>
    <third>bob</third>
    <third>charlie</third>
  </second>
</first>

, который я хотел бы преобразовать в:

<first>
  <second>
    <third>xavier</third>
    <third>yvonne</third>
    <third>charlie</third>
  </second>
</first>

Я думал, что приведенный ниже xsl будет работать, но это не так(Подозреваю по нескольким причинам).Что я делаю не так?

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

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

 <xsl:template match="/first/second/third/">
   <xsl:choose>
     <xsl:when test="contains(text(), 'alice')">
       <xsl:text>xavier</xsl:text>
     </xsl:when>
     <xsl:when test="contains(text(), 'bob')">
       <xsl:text>Yvonne</xsl:text>
   </xsl:when>
   <xsl:otherwise>
     <xsl:value-of select="text()"/>
   </xsl:otherwise>
   </xsl:choose>
 </xsl:template>

</xsl:stylesheet>

1 Ответ

0 голосов
/ 11 октября 2018

Две вещи, которые вы делаете неправильно:

  • У вас есть косая черта в конце этой XPath /first/second/third/.Синтаксически, недопустимо иметь косую черту в конце XPath, и она вам здесь не нужна.
  • У вас есть шаблон, который должен соответствовать third элементам (в основном, заменяяони когда-то были), но вы не копируете элементы.Вы просто заменяете их текстом, что означает, что у вас будет такой результат, как:
<first>
  <second>xavieryvonnecharlie</second>
</first>

Чтобы попытаться работать, достаточно изменить шаблон так:

<xsl:template match="/first/second/third">
  <xsl:copy>
    <xsl:choose>
      <xsl:when test="contains(text(), 'alice')">
        <xsl:text>xavier</xsl:text>
      </xsl:when>
      <xsl:when test="contains(text(), 'bob')">
        <xsl:text>Yvonne</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="text()"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:copy>
</xsl:template>

Однако это можно сделать намного более просто, если иметь шаблоны, соответствующие текстовым узлам, которые вы хотите заменить:

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

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

  <xsl:template match="third/text()[. = 'alice']">xavier</xsl:template>

  <xsl:template match="third/text()[. = 'bob']">yvonne</xsl:template>

</xsl:stylesheet>

При запуске на вводе образца вы получите:

<first>
   <second>
      <third>xavier</third>
      <third>yvonne</third>
      <third>charlie</third>
   </second>
</first>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...