XSLT в стиле фанк XML - PullRequest
       1

XSLT в стиле фанк XML

0 голосов
/ 09 октября 2011

Итак, я пытаюсь перевести некоторый XML в простой формат для выгрузки в БД.Вот как это выглядит:

<?xml version="1.0" encoding="UTF-8"?>
<detail type="Courses Taken" gm_recid="FNBYHVW(,7()E)S" >
          <properties>
            <property name="reference" >
              <property_string>M2</property_string>
            </property>
            <property name="Month YYYY" db_name="TITLE" >
              <property_string></property_string>
            </property>
            <property name="City, State" db_name="LINKACCT" >
              <property_string></property_string>
            </property>
          </properties>
</detail>

, который я бы предпочел выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<courses_taken>
    <gm_recid>FNBYHVW(,7()E)S</gm_recid>
    <reference>M2</reference>
    <date></date>
    <location></location>
</courses_taken>

Я не слишком знаком с XSL, поэтому я в растерянностикогда начать.Может ли кто-нибудь указать мне правильное направление?

Ответы [ 2 ]

2 голосов
/ 09 октября 2011

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

<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:variable name="vUpper" select=
 "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:variable name="vLower" select=
 "'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vDigits" select=
 "'0123456789'"/>

 <xsl:variable name="vAlphaNum" select=
  "concat($vUpper, $vLower, $vDigits, '_')"/>

 <xsl:template match="detail">
  <xsl:element name=
  "{translate(@type,
              translate(@type, $vAlphaNum, ''),
              '______________________________'
              )}">
   <xsl:apply-templates select=
     "@*[not(name()='type')]|*"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="detail/@*">
  <xsl:element name=
  "{translate(name(),
              translate(name(), $vAlphaNum, ''),
              '______________________________'
              )}">

   <xsl:value-of select="."/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="property[@name='reference']">
  <reference>
   <xsl:value-of select="."/>
  </reference>
 </xsl:template>

 <xsl:template match="property[@name='Month YYYY']">
  <date>
   <xsl:value-of select="."/>
  </date>
 </xsl:template>

 <xsl:template match="property[@name='City, State']">
  <location>
   <xsl:value-of select="."/>
  </location>
 </xsl:template>
</xsl:stylesheet>

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

<detail type="Courses Taken" gm_recid="FNBYHVW(,7()E)S" >
          <properties>
            <property name="reference" >
              <property_string>M2</property_string>
            </property>
            <property name="Month YYYY" db_name="TITLE" >
              <property_string></property_string>
            </property>
            <property name="City, State" db_name="LINKACCT" >
              <property_string></property_string>
            </property>
          </properties>
</detail>

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

<Courses_Taken>
   <gm_recid>FNBYHVW(,7()E)S</gm_recid>
   <reference>M2</reference>
   <date/>
   <location/>
</Courses_Taken>

Объяснение : Использование варианта метода двойного перевода *1019*, впервые предложенного @Michael Kay:

Если у нас есть строка $s и строка только допустимых символов $valid, и мы хотим получить от $s другую строку $s2, которая содержит только действительный символ $s (в их первоначальном порядке ), это может быть достигнуто путем вычисления следующего выражения XPath:

translate($s, translate($s, $valid, ''), '')

В данном конкретном случае мы хотим не удалять недопустимые символы, а заменить каждый из них на "_".

Мы предполагаем, что имя кандидата не будет превышать длину 30 , и используем строку замены фиксированной длины (это, конечно, может быть сделано так, как хотелось бы):

translate($s, 
          translate($s, $valid, ''), 
         '______________________________')
1 голос
/ 09 октября 2011

Это должно привести к началу работы:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes"/>

<xsl:template name="replace">
<xsl:param name="ptext"/>
<xsl:param name="ppattern"/>
<xsl:param name="preplacement"/>

<xsl:choose>
  <xsl:when test="not(contains($ptext, $ppattern))">
    <xsl:value-of select="$ptext"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="substring-before($ptext, $ppattern)"/>
    <xsl:value-of select="$preplacement"/>
    <xsl:call-template name="replace">
      <xsl:with-param name="ptext"
        select="substring-after($ptext, $ppattern)"/>
      <xsl:with-param name="ppattern" select="$ppattern"/>
      <xsl:with-param name="preplacement" select="$preplacement"/>
    </xsl:call-template>
  </xsl:otherwise>
</xsl:choose>
</xsl:template>



<xsl:template match="detail">
    <xsl:variable name="elemName">
      <xsl:call-template name="replace">
        <xsl:with-param name="ppattern" select="' '"/>
        <xsl:with-param name="ptext" select="@type"/>
        <xsl:with-param name="preplacement" select="'_'"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:element name="{$elemName}">
      <gm_recid>
        <xsl:value-of select="@gm_recid"/>
      </gm_recid>
      <xsl:apply-templates select="properties"/>
    </xsl:element>

  </xsl:template>


  <xsl:template match="properties">
    <xsl:for-each select="property">
        <!--Do something...-->
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

Ваши свойства содержат пробел и / или другие недопустимые символы элемента, поэтому вам, вероятно, придется решить, что делать с индивидуально.

Также замените шаблон, взятый отсюда:

Заменить несколько символов в строке (XSLT)

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