вторник, 30 ноября 2010 г.

XSL Template для замены CRLF на <br />

sabj :


<xsl:template name="substitute">
<xsl:param name="string" />
<xsl:param name="from" select="'&#xA;'" />
<xsl:param name="to">
<br />
</xsl:param>
<xsl:choose>
<xsl:when test="contains($string, $from)">
<xsl:value-of select="substring-before($string, $from)" />
<xsl:copy-of select="$to" />
<xsl:call-template name="substitute">
<xsl:with-param name="string"
select="substring-after($string, $from)" />
<xsl:with-param name="from" select="$from" />
<xsl:with-param name="to" select="$to" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>


Вызываем так:

<xsl:call-template name="substitute">
<xsl:with-param name="string" select="." />
</xsl:call-template>

P.S.: За подсветку кода спасибо маньякам ;)

понедельник, 2 августа 2010 г.

ORA-04052: error occurred when looking up remote object

Нашел сообщение в черновике, которое написал уже давно, и решил опубликовать, т.к. на днях разобрались с этой историей.

Накатывал большой патч на серверную логику продуктивной БД. Изменения в пакетах, триггерах, альтеры таблиц и пр. После чего получил инвалидные объекты с ошибками следующего содержания:


Error: PL/SQL: ORA-04052: error occurred when looking up remote object CMS.USERS_TABLE@DB1.RESTRICTED
ORA-00604: error occurred at recursive SQL level 1
ORA-03106: fatal two-task communication protocol error
ORA-02063: preceding line from DB1.RESTRICTED
Line: 35
Text: insert into users_table@db1.restricted(login_id,user_name,serv_group_id,


DBA в отпуске был. Два часа часть функционала была недоступна. Google навел меня на информацию о баге в Oracle 9, проявляющуюся при компиляции кода, где есть связь по dblink с базой на другой платформе. В нашем случае это был Oracle 9.2.0.8 на Solaris SPARC и та-же версия на CentOS x86.
Придумал быстрый workaround: создать на той же базе схему c таким же именем и с объектами, на которые смотрит dblink(благо объектов было всего с десяток), в tnsnames заменить адрес удаленной базы на локальную, перекомпилить пакеты и поменять tnsnames обратно.
C этой страшной багой мы жили несколько месяцев, каждый раз боясь инвалидировать код, работающий с dblink'ом, но все равно пару раз повторялось.

Все это закончилось тем, что мы наконец перешли на 10g, где такой ошибки нет. Ура!!!

суббота, 24 апреля 2010 г.

Converting XML to CSV through XSL

В интернете достаточно примеров по преобразованию XML в CSV по средствам XSL, но все они заточены под американские стандарты, т.е. тупо значения, с запятой в качестве разделителя. Мне нужно было получить значения в двойных ковычках, с разделителем ";" и если в тексте встречается двойная ковычка, то она должна заменяться на две двойных ковычки. Подробности о CSV в википедии.

Исходный XML:

<?xml version="1.0" encoding="windows-1251"?>
<catalog>
       <cd>
               <title>Empire "Burlesque"</title>
               <artist>Bob Dylan</artist>
               <country>USA</country>
               <company>&quot;Columbia&quot;</company>
               <price>10.90</price>
               <year>1985</year>
       </cd>
       <cd>
               <title>Hide your heart</title>
               <artist>Bonnie Tyler</artist>
               <country>UK</country>
               <company>CBS Records</company>
               <price>9.90</price>
               <year>1988</year>
       </cd>
       <cd>
               <title>Greatest Hits</title>
               <artist>Dolly Parton</artist>
               <country>USA</country>
               <company>RCA</company>
               <price>9.90</price>
               <year>1982</year>
       </cd>
       <cd>
               <title>Still got the blues</title>
               <artist>Gary Moore</artist>
               <country>UK</country>
               <company>Virgin records</company>
               <price>10.20</price>
               <year>1990</year>
       </cd>
       <cd>
               <title>Eros</title>
               <artist>Eros Ramazzotti</artist>
               <country>EU</country>
               <company>BMG</company>
               <price>9.90</price>
               <year>1997</year>
       </cd>
</catalog>


XSL шаблон:

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

<xsl:variable name="qt">
  <xsl:text>"</xsl:text>
</xsl:variable>
<xsl:variable name="dqt">
  <xsl:text>""</xsl:text>
</xsl:variable>

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

<xsl:template match="cd">
  <xsl:for-each select="*">
   <xsl:value-of select="$qt"/>
   <xsl:call-template name="replace-substring">
      <xsl:with-param name="original" select="."/>
      <xsl:with-param name="substring" select="$qt"/>
      <xsl:with-param name="replacement" select="$dqt"/>
   </xsl:call-template>
     <xsl:value-of select="$qt"/>
   <xsl:if test="position() != last()">
    <xsl:text>;</xsl:text>
   </xsl:if>
  </xsl:for-each>
  <xsl:text>&#13;&#10;</xsl:text>
</xsl:template>

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

</xsl:stylesheet>


И результат:

"Empire ""Burlesque""";"Bob Dylan";"USA";"""Columbia""";"10.90";"1985"
"Hide your heart";"Bonnie Tyler";"UK";"CBS Records";"9.90";"1988"
"Greatest Hits";"Dolly Parton";"USA";"RCA";"9.90";"1982"
"Still got the blues";"Gary Moore";"UK";"Virgin records";"10.20";"1990"
"Eros";"Eros Ramazzotti";"EU";"BMG";"9.90";"1997"