2013-05-24 4 views
0

Я использую XSLT для преобразования XML-файлов в формат, который Excel может разграничить (пример кода показан ниже). Например, при открытии в Excel, то разделителями версия может выглядеть примерно так:Использование XSLT для разбиения строки

+---------------+---------------+----------+ 
|URL   |Title   | Version | 
+---------------+---------------+----------+ 
|dogs_are_cool |Dogs are cool | May 2013 | 
+---------------+---------------+----------+ 

Проблема связана с тем, что каждый URL имеет версию вставляться в конце. Используя предыдущий пример, dogs_are_cool на самом деле dogs_are_cool_may2013.html.

Я хотел бы сделать две вещи с этой приложенном версии:

  • Удалить версию при печати URL.
  • Реформат и печать версии.

Я предполагаю, что лучший способ сделать это - каким-то образом разделить URL-адрес на символы подчеркивания. Затем поместите последний элемент в одну переменную и напечатайте остальные элементы в порядке - вставляя символы подчеркивания обратно.

Я не уверен, как это сделать.

Пример XML:

<contents Url="toc_animals_may2013.html" Title="Animals"> 
    <contents Url="toc_apes_may2013.html" Title="Apes"> 
     <contents Url="chimps_may2013.html" Title="Some Stuff About Chimps" /> 
    </contents> 
    <contents Url="toc_cats" Title="Cats"> 
     <contents Url="hairless_cats_may2013.html" Title="OMG Where Did the Hair Go?"/> 
     <contents Url="wild_cats_may2013.html" Title="These Things Frighten Me"/> 
    </contents> 
    <contents Url="toc_dogs_may2013.html" Title="Dogs"> 
     <contents Url="toc_snorty_dogs_may2013.html" Title="Snorty Dogs"> 
      <contents Url="boston_terriers_may2013.html" Title="Boston Terriers" /> 
      <contents Url="french_bull_dogs_may2013.html" Title="Frenchies" /> 
     </contents> 
    </contents> 
</contents> 

Пример XSLT:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" indent="no"/> 

    <!-- This variable sets the delimiter symbol that Excel will use to seperate the cells --> 
    <xsl:variable name="delimiter">@</xsl:variable> 

    <xsl:template match="contents"> 

     <!-- Prints the URL --> 
     <xsl:value-of select="@Url"/> 
     <xsl:copy-of select="$delimiter" /> 

     <!-- Prints the title --> 
     <xsl:apply-templates select="@Title"/> 
     <xsl:copy-of select="$delimiter" /> 

     <!-- I'd like to print the version here --> 
     <xsl:copy-of select="$delimiter" /> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="//contents"/> 
    </xsl:template> 

</xsl:stylesheet> 

ответ

1

Добавить еще несколько шаблонов, чтобы помочь нам, и мы создаем XSLT зверя, но это, кажется, сделать трюк ...

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" indent="no"/> 
    <!-- This variable sets the delimiter symbol that Excel will use to seperate the cells --> 
    <xsl:variable name="delimiter">@</xsl:variable> 

    <xsl:template match="contents"> 
    <!-- Prints the URL --> 
    <xsl:choose> 
     <xsl:when test="contains(@Url, '.')"> 
     <xsl:call-template name="substring-before-last"> 
      <xsl:with-param name="list" select="@Url"/> 
      <xsl:with-param name="delimiter" select="'_'"/> 
     </xsl:call-template>    
     </xsl:when> 
     <xsl:otherwise><xsl:value-of select="@Url"/></xsl:otherwise> 
    </xsl:choose> 
    <xsl:copy-of select="$delimiter"/> 

    <!-- Prints the title --> 
    <xsl:apply-templates select="@Title"/> 
    <xsl:copy-of select="$delimiter"/> 

    <!-- Now do all the tricks to format the version --> 
    <xsl:variable name="withExtension"> 
     <xsl:call-template name="substring-after-last"> 
     <xsl:with-param name="string" select="@Url"/> 
     <xsl:with-param name="delimiter" select="'_'"/> 
     </xsl:call-template> 
    </xsl:variable> 

    <xsl:variable name="withoutExtension"> 
     <xsl:call-template name="substring-before-last"> 
     <xsl:with-param name="list" select="$withExtension"/> 
     <xsl:with-param name="delimiter" select="'.'"/> 
     </xsl:call-template> 
    </xsl:variable> 

    <xsl:variable name="withoutSpace"> 
     <xsl:value-of select="concat(translate(substring($withoutExtension, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring($withoutExtension, 2))"/> 
    </xsl:variable> 

    <xsl:variable name="year"> 
     <xsl:value-of select="translate($withoutSpace,translate($withoutSpace, '', ''), '')"/> 
    </xsl:variable> 

    <xsl:value-of select="concat(substring-before($withoutSpace, $year), ' ', $year)"/> 
    <xsl:copy-of select="$delimiter"/> 
    </xsl:template> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="//contents"/> 
    </xsl:template> 

    <xsl:template name="substring-before-last"> 
    <xsl:param name="list"/> 
    <xsl:param name="delimiter"/> 
    <xsl:choose> 
     <xsl:when test="contains($list, $delimiter)"> 
     <xsl:value-of select="substring-before($list,$delimiter)"/> 
     <xsl:choose> 
      <xsl:when test="contains(substring-after($list,$delimiter),$delimiter)"> 
      <xsl:value-of select="$delimiter"/> 
      </xsl:when> 
     </xsl:choose> 
     <xsl:call-template name="substring-before-last"> 
      <xsl:with-param name="list" select="substring-after($list,$delimiter)"/> 
      <xsl:with-param name="delimiter" select="$delimiter"/> 
     </xsl:call-template> 
     </xsl:when> 
    </xsl:choose> 
    </xsl:template> 

    <xsl:template name="substring-after-last"> 
    <xsl:param name="string"/> 
    <xsl:param name="delimiter"/> 
    <xsl:choose> 
     <xsl:when test="contains($string, $delimiter)"> 
     <xsl:call-template name="substring-after-last"> 
      <xsl:with-param name="string" select="substring-after($string, $delimiter)"/> 
      <xsl:with-param name="delimiter" select="$delimiter"/> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="$string"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

Выход:

[email protected]@May [email protected][email protected]@May [email protected]@Some Stuff About [email protected] [email protected][email protected]@ @[email protected] Where Did the Hair [email protected] [email protected][email protected] Things Frighten [email protected] [email protected][email protected]@May [email protected][email protected] [email protected] [email protected][email protected] [email protected] [email protected][email protected]@May [email protected] 
+0

Это прекрасно работает! Спасибо за помощь! – mrthetooth

2

Если вы можете использовать XSLT 2.0, это станет намного проще.

XML Input

<contents Url="toc_animals_may2013.html" Title="Animals"> 
    <contents Url="toc_apes_may2013.html" Title="Apes"> 
     <contents Url="chimps_may2013.html" Title="Some Stuff About Chimps" /> 
    </contents> 
    <contents Url="toc_cats" Title="Cats"> 
     <contents Url="hairless_cats_may2013.html" Title="OMG Where Did the Hair Go?"/> 
     <contents Url="wild_cats_may2013.html" Title="These Things Frighten Me"/> 
    </contents> 
    <contents Url="toc_dogs_may2013.html" Title="Dogs"> 
     <contents Url="toc_snorty_dogs_may2013.html" Title="Snorty Dogs"> 
      <contents Url="boston_terriers_may2013.html" Title="Boston Terriers" /> 
      <contents Url="french_bull_dogs_may2013.html" Title="Frenchies" /> 
     </contents> 
    </contents> 
</contents> 

XSLT 2,0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:param name="delim" select="'@'"/> 

    <xsl:template match="contents"> 
     <xsl:variable name="urlTokens" select="tokenize(@Url,'_')"/> 
     <xsl:value-of select="$urlTokens[not(position() = last())]" separator="_"/> 
     <xsl:value-of select="$delim"/> 
     <xsl:value-of select="concat(@Title,$delim)"/> 
     <xsl:analyze-string select="$urlTokens[last()]" regex="([a-z])([a-z]+)([0-9]+)"> 
      <xsl:matching-substring> 
       <xsl:value-of select="concat(upper-case(regex-group(1)),regex-group(2),' ',regex-group(3))"/>    
      </xsl:matching-substring> 
     </xsl:analyze-string> 
     <xsl:text>&#xA;</xsl:text> 
     <xsl:apply-templates/> 
    </xsl:template> 

</xsl:stylesheet> 

Выход

[email protected]@May 2013 
[email protected]@May 2013 
[email protected] Stuff About [email protected] 2013 
[email protected]@ 
[email protected] Where Did the Hair [email protected] 2013 
[email protected] Things Frighten [email protected] 2013 
[email protected]@May 2013 
[email protected] [email protected] 2013 
[email protected] [email protected] 2013 
[email protected]@May 2013 
+0

Спасибо, Дэниэл. Решение 2.0, безусловно, намного проще, но Excel, похоже, не похож на 2.0. – mrthetooth

Смежные вопросы