Изменить документ XML с помощью XSLT - PullRequest
4 голосов
/ 17 сентября 2011

Я пытаюсь понять, есть ли способ изменить XML-документ с использованием XSLT или есть ли другие, более подходящие, чем XSLT?

Скажем, у меня есть XML как:*

Я хотел бы выполнить следующие действия:

  1. Изменить фид: id на (удалить текст фида: id)
  2. Изменить запись: значения id, чтобыостается последнее числовое значение после "/".

Результат xml должен выглядеть примерно так:

<feed xmlns="http://www.w3.org/2005/Atom">
<id></id>
<entry>
<id>2</id>
</entry>
<entry>
<id>3</id>
</entry>
</feed>

Спасибо, Sony

Ответы [ 2 ]

4 голосов
/ 17 сентября 2011

I. Решение XSLT 1.0:

Это преобразование XSLT 1.0 работает с любым URL без каких-либо предположений обо всех URL-адресах, имеющих общую начальную подстроку:

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

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

 <xsl:template match="x:feed/x:id/node()"/>

 <xsl:template match="x:entry/x:id/text()" name="eatSlashes">
  <xsl:param name="pText" select="."/>

  <xsl:choose>
   <xsl:when test="not(contains($pText, '/'))">
    <xsl:value-of select="$pText"/>
   </xsl:when>
   <xsl:otherwise>
    <xsl:call-template name="eatSlashes">
     <xsl:with-param name="pText" select=
                   "substring-after($pText, '/')"/>
    </xsl:call-template>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

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

<feed xmlns="http://www.w3.org/2005/Atom">
    <id>http://libx.org/libx2/libapps</id>
    <entry>
        <id>http://libx.org/libx2/libapps/2</id>
    </entry>
    <entry>
        <id>http://libx.org/libx2/libapps/3</id>
    </entry>
</feed>

желаемый, правильный результат получается :

<feed xmlns="http://www.w3.org/2005/Atom">
   <id/>
   <entry>
      <id>2</id>
   </entry>
   <entry>
      <id>3</id>
   </entry>
</feed>

II. Решение XSLT 2.0 :

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

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

 <xsl:template match="x:feed/x:id/node()"/>

 <xsl:template match="x:entry/x:id/text()">
  <xsl:sequence select="tokenize(.,'/')[last()]"/>
 </xsl:template>
</xsl:stylesheet>

при применении к одному и тому же XML-документу (см. Выше), получается тот же правильный результат :

<feed xmlns="http://www.w3.org/2005/Atom">
   <id/>
   <entry>
      <id>2</id>
   </entry>
   <entry>
      <id>3</id>
   </entry>
</feed>
0 голосов
/ 17 сентября 2011

Мои знания XSLT не самые лучшие, но, похоже, это работает:

<?xml version="1.0" encoding="utf-8"?>
<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="a:feed/a:id" xmlns:a="http://www.w3.org/2005/Atom">
    <xsl:copy/>
  </xsl:template>
  <xsl:template match="a:entry/a:id" xmlns:a="http://www.w3.org/2005/Atom">
    <xsl:copy><xsl:value-of select="substring-after(.,'http://libx.org/libx2/libapps/')"/></xsl:copy>
  </xsl:template>

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