关于时髦的XML的XSLT

时间:2011-10-08 23:31:36

标签: xml xslt

所以,我正在尝试将一些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 个答案:

答案 0 :(得分:2)

完整的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>

解释:使用@Michael Kay首先提出的双翻译方法的变体:

如果我们有一个字符串$s和一串只允许的字符$valid,我们希望从$s获得另一个字符串$s2,其中只包含有效字符$s(按原始顺序),可以通过评估以下XPath表达式来实现:

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

在这种特殊情况下,我们不想删除无效字符,而是用 "_"替换每个字符。

我们假设候选名称不会超过30 的长度并使用固定长度的替换字符串(当然这可以根据需要制作):

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

答案 1 :(得分:1)

这应该让你开始:

<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>

您的属性包含空格和/或其他无效元素字符,因此您可能必须决定如何单独处理。

同时替换此处的模板:

Replace Multiple Characters in a String (XSLT)