Простая замена текста XSLT - PullRequest
2 голосов
/ 05 марта 2012

Я ищу более простой и элегантный способ замены текста в XML.Для исходного XML, такого как:

<A>
 <B>
  <Name>ThisOne</Name>
  <Target>abc</Target>
 </B>
 <B>
  <Name>NotThisOne</Name>
  <Target>abc</Target>
 </B>
 <B>
  <Name>ThisOne</Name>
  <Target>def</Target>
 </B>
</A>

Я хочу изменить текст всех элементов Target с именем «ThisOne» на «xyz».

В результате получится:

<A>
 <B>
  <Name>ThisOne</Name>
  <Target>xyz</Target>     <--   Changed.
 </B>
 <B>
  <Name>NotThisOne</Name>
  <Target>abc</Target>
 </B>
 <B>
  <Name>ThisOne</Name>
  <Target>xyz</Target>     <--   Changed.
 </B>
</A>

Я достиг этого с помощью:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="B/Target">
    <xsl:choose>
      <xsl:when test="../Name/text()='ThisOne'"><Target>xyz</Target></xsl:when>
      <xsl:otherwise><Target><xsl:value-of select="text()"/></Target></xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

Я думал, что это можно сделать сТаким образом, я мог бы просто заменить текст, а не весь элемент, но не смог разобраться с остальными.

Заранее спасибо.

Ответы [ 3 ]

5 голосов
/ 05 марта 2012

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

  <xsl:template match="B[Name='ThisOne']/Target/text()">
    <xsl:text>xyz</xsl:text>
  </xsl:template>

</xsl:stylesheet>

с использованием вашего ввода XML дает:

<A>
  <B>
    <Name>ThisOne</Name>
    <Target>xyz</Target>
  </B>
  <B>
    <Name>NotThisOne</Name>
    <Target>abc</Target>
  </B>
  <B>
    <Name>ThisOne</Name>
    <Target>xyz</Target>
  </B>
</A>
1 голос
/ 05 марта 2012
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cds="cds_dt" exclude-result-prefixes="cds">
    <!-- Identity transfrom - just copy what doesn't need changing -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- a rule for what does need changing -->
    <!-- Change all Target nodes whose parent has a child of Name equal to ThisOne -->
    <xsl:template match="/A/B[Name='ThisOne']/Target">
        <Target>xyz</Target>
    </xsl:template>
</xsl:stylesheet>
1 голос
/ 05 марта 2012

Это все, что вам нужно сделать:

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

 <xsl:template match="B/Target[../Name='ThisOne']">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:text>xyz</xsl:text>
  </xsl:copy>
 </xsl:template>

Первый шаблон представляет собой «преобразование идентичности» и копирует входные данные в выходные данные без изменений. Второй соответствует конкретным целям, которые вы хотите изменить, копирует тег и атрибуты и заменяет нужный текст.

...