OdbcParameterCollection приема само ненулеви обекти от тип OdbcParameter

Само като малко предупреждение, аз съм напълно нов в цялото това нещо с „кодирането“ като цяло, така че ме извинете, ако не съм се изразил ясно и просто ме уведомете, ако мога да ви кажа нещо друго. Търсих в Google от дни и не можах да намеря нищо, не съм сигурен дали това е лошо от моя страна или просто защото съм наистина нов и не бих знаел решението, ако беше точно пред мен лице.

Когато отида да тествам приложението (Visual Studio 2010), всичко се показва и мога да въвеждам информация в текстовите си полета, но след като натисна бутона за изпращане, се появява тази грешка:

"OdbcParameterCollection приема само ненулеви обекти от тип OdbcParameter. Име на параметър: стойност"

и сочи към този ред код:

cmd.Parameters.Add(pram[i]);

Не знам дали задавам параметрите погрешно или изразът INSERT INTO е погрешен или какво. Мога да ви покажа и кода на ASP.net, ако е необходимо. Уведомете ме, ако мога да ви дам повече информация! Благодаря предварително!

Моят C# код е следният:

 private void execution(string eventspecialist, string phone, string phone2, string firstname, string lastname, string besttime, string companyname, string nonprofit, string requesteddate, string requestedtime, string attendance, string eventtype, string other, string leadsource, string notes, string catering, string bar, string damagedeposit, string dancefloor)
{


    OdbcConnection conn = new OdbcConnection(GetConnectionString());

    string sql = "INSERT INTO tblcontacts (eventspecialist, phone, phone2, firstname, lastname, besttime, companyname, nonprofit, requesteddate, requestedtime, attendance, eventtype, other, leadsource, notes, catering, bar, damagedeposit, dancefloor) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    try
    {
        conn.Open();
        OdbcCommand cmd = new OdbcCommand(sql, conn);

        cmd.Parameters.Add("@SPECIALIST", OdbcType.NVarChar, 50).Value = eventspecialist;
        cmd.Parameters.Add("@CUST_PHONE1", OdbcType.NVarChar, 50).Value = phone;
        cmd.Parameters.Add("@CUST_PHONE2", OdbcType.NVarChar, 50).Value = phone2;
        cmd.Parameters.Add("@CUST_FNAME", OdbcType.NVarChar, 50).Value = firstname;
        cmd.Parameters.Add("@CUST_LNAME", OdbcType.NVarChar, 50).Value = lastname;
        cmd.Parameters.Add("@BEST_TIME", OdbcType.NVarChar, 50).Value = besttime;
        cmd.Parameters.Add("@COMPANY_NAME", OdbcType.NVarChar, 225).Value = companyname;
        cmd.Parameters.Add("@NONPROFIT", OdbcType.NVarChar, 1).Value = nonprofit;
        cmd.Parameters.Add("@REQ_DATE", OdbcType.NVarChar, 10).Value = requesteddate;
        cmd.Parameters.Add("@REQ_TIME", OdbcType.NVarChar, 20).Value = requestedtime;
        cmd.Parameters.Add("@ATTENDANCE", OdbcType.NVarChar, 50).Value = attendance;
        cmd.Parameters.Add("@EVENT_TYPE", OdbcType.NVarChar, 50).Value = eventtype;
        cmd.Parameters.Add("@OTHER_DESC", OdbcType.NVarChar, 225).Value = other;
        cmd.Parameters.Add("@LEAD_SOURCE", OdbcType.NVarChar, 50).Value = leadsource;
        cmd.Parameters.Add("@NOTES", OdbcType.NVarChar, 225).Value = notes;
        cmd.Parameters.Add("@CATERING", OdbcType.NVarChar, 1).Value = catering;
        cmd.Parameters.Add("@BAR", OdbcType.NVarChar, 1).Value = bar;
        cmd.Parameters.Add("@DAMAGE_DEPOSIT", OdbcType.NVarChar, 19).Value = damagedeposit;
        cmd.Parameters.Add("@DANCE_FLOOR", OdbcType.NVarChar, 19).Value = dancefloor;



        cmd.CommandType = CommandType.Text;
        cmd.ExecuteNonQuery();
    }
    catch (System.Data.Odbc.OdbcException ex_msg)
    {

        string msg = "Error occured while inserting";
        msg += ex_msg.Message;
        throw new Exception(msg);
    }
    finally
    {

        conn.Close();
    }
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void submit_Click(object sender, EventArgs e)
{
    execution(eventspecialist.Text, phone.Text, phone2.Text, firstname.Text, lastname.Text, besttime.SelectedItem.Text, companyname.Text, nonprofit.Text, requesteddate.Text, requestedtime.Text, attendance.Text, eventtype.SelectedItem.Text, other.Text, leadsource.SelectedItem.Text, notes.Text, catering.Text, bar.Text, damagedeposit.Text, dancefloor.SelectedItem.Text);

    conform.Visible = true;
    Control frm = this.FindControl("form1");
    foreach (Control ctrl in frm.Controls)
    {
        if (ctrl is TextBox)
        {
            ((TextBox)ctrl).Text = "";
        }
        else if (ctrl is CheckBox)
        {
            ((CheckBox)ctrl).Checked = false;
        }
        else if (ctrl is DropDownList)
        {
            ((DropDownList)ctrl).SelectedIndex = 0;
        }
    }
}

person Control    schedule 25.01.2012    source източник
comment
кой сървър на база данни използвате mysql???   -  person Devjosh    schedule 25.01.2012
comment
Използвам ODBC източник на данни за SQL Server Native Client 10.0. Ако това питаш?   -  person Control    schedule 25.01.2012
comment
Защо не използвате SqlClient? msdn.microsoft.com/en-us/library/system. data.sqlclient.aspx msdn.microsoft .com/en-us/library/   -  person Lloyd    schedule 25.01.2012
comment
Защото всеки път, когато го използвах, ми дава грешка, че ключовата дума „dsn“ не се поддържа, което след търсене онлайн някой препоръча да използвам ODBC вместо това. Не съм сигурен дали това беше мъдро решение.   -  person Control    schedule 25.01.2012


Отговори (4)


Получавате нулева препратка, защото сте създали и сте задали размера на pram, но не сте добавили никакви обекти към него. И така, това, което имате, е масив, пълен с нули. Изглежда, че можете напълно да премахнете цикъла for и масива pram, защото вече добавяте параметрите към cmd извън цикъла.

Следният код е ненужен:

OdbcParameter[] pram = new OdbcParameter[19];

и също

for (int i = 0; i < pram.Length; i++)
{
    cmd.Parameters.Add(pram[i]);
}

Освен това трябва да зададете стойностите на всеки параметър по следния начин:

cmd.Parameters.Add("@SPECIALIST", OdbcType.NVarChar, 50).Value = eventspecialist;

И така, вашият блок try ще изглежда така:

try
{
    conn.Open();
    OdbcCommand cmd = new OdbcCommand(sql, conn);

    cmd.Parameters.Add("@SPECIALIST", OdbcType.NVarChar, 50).Value = eventspecialist;
    cmd.Parameters.Add("@CUST_PHONE1", OdbcType.NVarChar, 50).Value = phone;
    cmd.Parameters.Add("@CUST_PHONE2", OdbcType.NVarChar, 50).Value = phone2;
    cmd.Parameters.Add("@CUST_FNAME", OdbcType.NVarChar, 50).Value = firstname;
    cmd.Parameters.Add("@CUST_LNAME", OdbcType.NVarChar, 50).Value = lastname;
    cmd.Parameters.Add("@BEST_TIME", OdbcType.NVarChar, 50).Value = besttime;
    cmd.Parameters.Add("@COMPANY_NAME", OdbcType.NVarChar, 225).Value = companyname;
    cmd.Parameters.Add("@NONPROFIT", OdbcType.NVarChar, 1).Value = nonprofit;
    cmd.Parameters.Add("@REQ_DATE", OdbcType.Date, 10).Value = requesteddate;
    cmd.Parameters.Add("@REQ_TIME", OdbcType.Time, 20).Value = requestedtime;
    cmd.Parameters.Add("@ATTENDANCE", OdbcType.NVarChar, 50).Value = attendance;
    cmd.Parameters.Add("@EVENT_TYPE", OdbcType.NVarChar, 50).Value = eventtype;
    cmd.Parameters.Add("@OTHER_DESC", OdbcType.NVarChar, 225).Value = other;
    cmd.Parameters.Add("@LEAD_SOURCE", OdbcType.NVarChar, 50).Value = leadsource;
    cmd.Parameters.Add("@NOTES", OdbcType.NVarChar, 225).Value = notes;
    cmd.Parameters.Add("@CATERING", OdbcType.NVarChar, 1).Value = catering;
    cmd.Parameters.Add("@BAR", OdbcType.NVarChar, 1).Value = bar;
    cmd.Parameters.Add("@DAMAGE_DEPOSIT", OdbcType.NVarChar, 19).Value = damagedeposit;
    cmd.Parameters.Add("@DANCE_FLOOR", OdbcType.NVarChar, 19).Value = dancefloor;

    cmd.CommandType = CommandType.Text;
    cmd.ExecuteNonQuery();

}

От редакцията на въпроса ви виждам, че това е кодът, който използвате, и предполагам, че все още получавате същата грешка? Това най-вероятно означава, че една от стойностите, които добавяте към колекцията от параметри, е нула. Ако ги проверите с дебъгера, всички ли имат зададени стойности?

Редактиране отново:

Има още една грешка, която пропуснах преди. SQL командата, която сте написали за ODBC, използва параметри неправилно, както е посочено от новата грешка.

string sql = "INSERT INTO tblcontacts (eventspecialist, phone, phone2, firstname, lastname, besttime, companyname, nonprofit, requesteddate, requestedtime, attendance, eventtype, other, leadsource, notes, catering, bar, damagedeposit, dancefloor) 
VALUES (@SPECIALIST, @CUST_PHONE1, @CUST_PHONE2, @CUST_FNAME, @CUST_LNAME, @BEST_TIME, @COMPANY_NAME, @NONPROFIT, @REQ_DATE, @REQ_TIME, @ATTENDANCE, @EVENT_TYPE, @OTHER_DESC, @LEAD_SOURCE, @NOTES, @CATERING, @BAR, @DAMAGE_DEPOSIT, @DANCE_FLOOR)";

Би трябвало:

string sql = "INSERT INTO tblcontacts (eventspecialist, phone, phone2, firstname, lastname, besttime, companyname, nonprofit, requesteddate, requestedtime, attendance, eventtype, other, leadsource, notes, catering, bar, damagedeposit, dancefloor) 
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

Моля, имайте предвид, че разделих реда код за четливост. Освен това редът, в който добавяте вашите параметри към колекцията, има значение. Те трябва да са в реда, който съответства на колоните (стойността за eventspecialist трябва да е първа, тази за phon втора и т.н.) Може да се окаже, че трябва да наименувате вашите параметри по същия начин като имената на колоните, като @shahkalpesh предлага.

ODBC командите използват ? за достъп до параметри, а не името на параметъра, както правят SQL командите. Няколко линка по темата:

http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx

http://msdn.microsoft.com/en-us/library/8dcw81x5.aspx

Редактиране

Забелязвам, че предавате всички стойности на метода като string. Ще трябва да ги конвертирате в правилния тип и да използвате правилния тип ODBC данни, когато добавяте параметри. Моля, вижте тази връзка за типове ODBC параметри.

Използвайте какъвто и тип да е колоната (varchar, money и т.н.) и ако вашите променливи (eventspecialist и т.н.) не са от правилния тип, преобразувайте стойностите в правилния тип (както е посочено във връзката), преди да ги добавите. Например cmd.Parameters.Add("@ATTENDANCE", OdbcType.Int).Value = Int32.Parse(attendance);. Моля, имайте предвид, че Int32.Parse може да изведе грешка, ако attendance не е низ, който представлява цяло число. Предлагам да промените сигнатурата на метода, за да изисква правилните типове, след което да ги валидирате и конвертирате преди извикването на execution. Това ще избегне грешки при преобразуване на типа при този метод. По този начин, ако получите грешка тук, знаете, че тя е свързана с взаимодействието с DB, а не с неправилната настройка на командата.

person Esoteric Screen Name    schedule 25.01.2012
comment
Така че, за да се уверите, имате предвид премахване за (int i = 0; i ‹ pram.Length; i++) { cmd.Parameters.Add(pram[i]); } и какво друго? - person Control; 25.01.2012
comment
Да, можете да премахнете целия цикъл for. Тъй като не сте поставили нищо в масива на количката, няма да получите нищо от него и оттам идва нулевата стойност. Но тъй като ръчно добавяте параметрите към командата (cmd.Parameters.Add(...); и cmd.Parameters[xxx].Value = xxx;), не е необходимо да ги добавяте отново. Можете също да премахнете реда OdbcParameter[] pram = new OdbcParameter[19]; Редактирах отговора си, за да бъда по-ясен. - person Esoteric Screen Name; 25.01.2012
comment
@Kruce: Премахнете OdbcParameter[] и цялото му използване. Използвайте .Value = x вместо това. - person abatishchev; 25.01.2012
comment
Къде бих поставил .Value = x, просто където и да е OdbcParameter[]? Така например .Value pram = new .Value = 19? Или това просто вървеше в грешната посока? - person Control; 25.01.2012
comment
Бихте добавили .Value = x към всеки cmd.Parameters.Add(...); ред и премахнете всеки cmd.Parameters["@x"].Value = x; ред. Ще редактирам отговора си с пълен пример. - person Esoteric Screen Name; 25.01.2012
comment
О, разбирам какво имаш предвид. Направих това и редактирах кода си сега, току-що получавам тази грешка: Възникна грешка при вмъкванеERROR [42000] [Microsoft][SQL Server Native Client 10.0][SQL Server]Трябва да декларира скаларната променлива @SPECIALIST. - person Control; 25.01.2012
comment
@Kruce: Предполагам, че ще трябва да назовете параметрите по същия начин като името на колоната, за да започнете. Моля вижте отговора, написал съм го по-горе. - person shahkalpeshp; 25.01.2012
comment
Имате предвид примера, който показва: cmd.Parameters.Add(eventspecialist, OdbcType.NVarChar, 50); Разбирам това, но как да свържа това с действителната си база данни @SPECIALIST? - person Control; 25.01.2012
comment
@Kruce Актуализирах отговора си, за да се справя с новата грешка, която получавате. - person Esoteric Screen Name; 25.01.2012
comment
Първоначално имах ?, ?, ?, ? и т.н., но се промених въз основа на отговорите. Вярвам, че всичко е в правилния ред. Новата грешка, която получавам, е ГРЕШКА [42S22] Невалидно име на колона 'eventspecialist' Което също се повтаря и за всички останали. Така че, когато казвате име на моите параметри като колоната, вие предлагате да преименувате eventspecialist на SPECILAIST? - person Control; 25.01.2012
comment
Придържайте се към ? използването. Липсата на това причиняваше грешката Must declare the scalar variable "@SPECIALIST". Как изглежда вашата дефиниция на таблицата? Тази грешка предполага, че таблицата tblcontacts няма колона с име eventspecialist. Вярвам, че предложението на shahkalpesh е да промените @SPECIALIST на eventspecialist в ред cmd.Parameters.Add(@SPECIALIST, ... - person Esoteric Screen Name; 25.01.2012
comment
Не, името на колоната ми в таблицата е SPECIALIST, 'eventspecialist' е името на текстовото поле, където потребителят поставя информация, която искам да бъде изпратена на моята маса. Напълно погрешно ли го правя? - person Control; 25.01.2012
comment
@Kruce - а, да. Трябва да използвате имената на колоните там, а не имената на текстовите полета. Така че трябва да бъде string sql = "INSERT INTO tblcontacts (SPECIALIST, ... - person Esoteric Screen Name; 25.01.2012
comment
Ааа, мисля, че може би току-що го направи. Сега получавам малки грешки като Неуспешно преобразуване на стойност на параметър от низ в десетична. Но вярвам, че това е така, защото декларирам всичко като NVarChar, когато някои неща са числови или пари. Имате ли някакви предложения за това, докато все още ви помагам? Освен това благодаря за търпението. - person Control; 25.01.2012
comment
@Kruce Актуализирам отговора си. - person Esoteric Screen Name; 25.01.2012
comment
Благодаря! Това беше наистина, наистина полезно. Както казах преди, аз съм супер нов във всичко това, така че имате ли лесен начин да обясните как всъщност да конвертирате към правилния тип или да промените сигнатурата на метода, за да изисква правилните типове, след което да ги валидирате и конвертирате преди извикването на екзекуция. Отново сериозно, благодаря за помощта. Не искам да се чувстваш така, сякаш трябва да ме мъчиш през всичко това, но всяка помощ е изключително ценена. :) - person Control; 25.01.2012
comment
Освен това DANCE_FLOOR е пари, но това не е ODBC. Тип? - person Control; 25.01.2012
comment
Няма проблем, някога всички са били нови. Бих опитал decimal за типа ODBC за параметъра DANCE_FLOOR. Вижте: msdn.microsoft.com/en-us/library/ms173105.aspx за преглед на основите на преобразуването на вашите низове в подходящите типове. Засега просто бих ги конвертирал в метода execution. След като накарате всичко да работи, преместете реализациите навън, за да подобрите структурата и променете метода на execute(string eventspecialist, ... , decimal dancefloor, etc). - person Esoteric Screen Name; 25.01.2012
comment
О, момче, това е съвсем различен проблем, върху който ще трябва да поработя! хаха! Благодаря за цялата помощ на всички по този въпрос и Esoteric. Оценявам го! - person Control; 25.01.2012

Грешката е, защото сте дефинирали масив (OdbcParameter[] pram = new OdbcParameter[19];). Но вие не инициализирате елементи от него.

Гледайки вашия код, следните редове във вашия код не са задължителни.

OdbcParameter[] pram = new OdbcParameter[19];

и

for (int i = 0; i < pram.Length; i++)
{
    cmd.Parameters.Add(pram[i]);
}

РЕДАКТИРАНЕ: Не съм използвал Odbc* класове в миналото.
Разглеждам конкретния пример тук, името на вашия параметър трябва да е същото като името на колоната ви

cmd.Parameters.Add("eventspecialist", OdbcType.NVarChar, 50);
cmd.Parameters.Add("phone", OdbcType.NVarChar, 50);
cmd.Parameters.Add("phone2", OdbcType.NVarChar, 50);
cmd.Parameters.Add("firstname", OdbcType.NVarChar, 50);
cmd.Parameters.Add("lastname", OdbcType.NVarChar, 50);
cmd.Parameters.Add("besttime", OdbcType.NVarChar, 50);

и така нататък за останалите параметри.

person shahkalpeshp    schedule 25.01.2012

защо правите това, ако вече сте добавили параметри в командния обект.

for (int i = 0; i < pram.Length; i++)
{
    cmd.Parameters.Add(pram[i]);
}

няма нужда това да се прави отново и също да се променя

string sql = "INSERT INTO tblcontacts (eventspecialist) VALUES (@SPECIALIST)"

по този начин.

person Ravi    schedule 25.01.2012

Добавете параметъра с дефинирана стойност, като се предполага, че стойностите, които предавате, не са нулеви, когато не са посочени.

В зависимост от базата данни имената на вашите параметри във вашата заявка трябва да съвпадат с имената на параметрите, дефинирани в колекцията OdbcParameters, и в някои случаи да са в правилния ред или приложение.

Според вашата актуализация, посочете имената на вашите параметри във вашата заявка.

string sql = "INSERT INTO tblcontacts (eventspecialist, phone, phone2, firstname, lastname, besttime, companyname, nonprofit, requesteddate, requestedtime, attendance, eventtype, other, leadsource, notes, catering, bar, damagedeposit, dancefloor) VALUES (@EVENTSPECIALIST, @CUST_PHONE1, ETC ETC ETC)"; 


// Remove this code.
OdbcParameter[] pram = new OdbcParameter[19]; 

for (int i = 0; i < pram.Length; i++) 
    { 
        cmd.Parameters.Add(pram[i]); 
    } 


// Add your parameters with a value.
cmd.Parameters.Add("@SPECIALIST", OdbcType.NVarChar, 50).Value = eventSpecialist;

Бих препоръчал също да използвате един от класовете за свързване на Native Database, където е приложимо, System.Data.SqlClient, MySql.Data.Client или клиента на Oracle.

person Lloyd    schedule 25.01.2012
comment
@Esoteric Screen Name защо не добавите сами пълен разумен отговор вместо коментари. - person Lloyd; 25.01.2012
comment
@Esoter: Моля, бъдете по-дружелюбни на SO - person abatishchev; 25.01.2012
comment
Направих това, но получих друга грешка Възникна грешка при вмъкванеERROR [42000] [Microsoft][SQL Server Native Client 10.0][SQL Server]Трябва да декларира скаларната променлива @SPECIALIST. Може ли да е, защото трябва да превключвам параметрите? Това, което имам предвид, е, че eventspecialist е низът в моя asp.net код, а SPECIALIST е името на базата данни, към което искам да бъде свързано това текстово поле. - person Control; 25.01.2012
comment
Отново, наистина ми простете, ако изобщо не разбирам, защото може да казвам всичко това погрешно. Оценявам всяка форма на помощ, която всеки може да даде. - person Control; 25.01.2012
comment
Можете ли да актуализирате кода си във въпроса, след което можем да видим какво сте направили? - person Lloyd; 25.01.2012
comment

Тази трансформация:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kAlbumByChildName" match="album" use="name(album_num/*[1])"/>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:apply-templates mode="pass2" select=
  "ext:node-set($vrtfPass1)/*
           [generate-id()
           =
            generate-id(key('kAlbumByChildName', name(album_num/*[1]))[1])
           ]
  "/>
 </xsl:template>

 <xsl:template match="album">
  <album>
   <album_num>
       <xsl:element name="{substring-before(album_num, '.')}">
         <xsl:element name="{substring-after(album_num, '.')}">
           <xsl:value-of select="album_name"/>
         </xsl:element>
       </xsl:element>
   </album_num>
  </album>
 </xsl:template>

 <xsl:template match="album" mode="pass2">
  <album>
   <album_num>
        <xsl:apply-templates select="*/*[1]" mode="pass2"/>
    </album_num>
  </album>
 </xsl:template>

 <xsl:template match="album_num/*" mode="pass2">
  <xsl:copy>
   <xsl:copy-of select="key('kAlbumByChildName', name())/*/*/*"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

когато се прилага върху следния документ (предоставеният XML фрагмент, обвит в един горен елемент, за да бъде добре оформен XML документ):

<t>
    <album>
        <album_num>hi.hello</album_num>
        <album_name>Cocktail</album_name>
    </album>
    <album>
        <album_num>hey.hello</album_num>
        <album_name>Mocktail</album_name>
    </album>
    <album>
        <album_num>hey.mello</album_num>
        <album_name>Monkeytail</album_name>
    </album>
    <album>
        <album_num>hey.yellow</album_num>
        <album_name>Donkeytail</album_name>
    </album>
</t>

произвежда желания правилен резултат:

<album>
   <album_num>
      <hi>
         <hello>Cocktail</hello>
      </hi>
   </album_num>
</album>
<album>
   <album_num>
      <hey>
         <hello>Mocktail</hello>
         <mello>Monkeytail</mello>
         <yellow>Donkeytail</yellow>
      </hey>
   </album_num>
</album>

Обяснение:

Това е двуходова трансформация. Резултатът от първото преминаване е:

<album>
   <album_num>
      <hi>
         <hello>Cocktail</hello>
      </hi>
   </album_num>
</album>

<album>
   <album_num>
      <hey>
         <hello>Mocktail</hello>
      </hey>
   </album_num>
</album>

<album>
   <album_num>
      <hey>
         <mello>Monkeytail</mello>
      </hey>
   </album_num>
</album>

<album>
   <album_num>
      <hey>
         <yellow>Donkeytail</yellow>
      </hey>
   </album_num>
</album>

Вторият проход е стандартно групиране на Muenchian.

Актуализация:

Два дни след като зададе този въпрос и получи правилен отговор, OP промени изходния XML документ и желания резултат.

Тази леко модифицирана трансформация:

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>

     <xsl:key name="kAlbumByChildName" match="album" use="name(album_num/*[1])"/>

     <xsl:template match="/">
      <xsl:variable name="vrtfPass1">
        <xsl:apply-templates/>
      </xsl:variable>

      <xsl:apply-templates mode="pass2" select=
      "ext:node-set($vrtfPass1)/*
               [generate-id()
               =
                generate-id(key('kAlbumByChildName', name(album_num/*[1]))[1])
               or
                not(album_num/*)
               ]
      "/>

     </xsl:template>

     <xsl:template match="album[contains(album_num, '.')]">
      <album>
       <album_num>
           <xsl:element name="{substring-before(album_num, '.')}">
             <xsl:element name="{substring-after(album_num, '.')}">
               <xsl:value-of select="album_name"/>
             </xsl:element>
           </xsl:element>
       </album_num>
      </album>
     </xsl:template>

     <xsl:template match="album">
      <album>
       <album_num>
             <xsl:element name="{album_num}">
               <xsl:value-of select="album_name"/>
             </xsl:element>
       </album_num>
      </album>
     </xsl:template>

     <xsl:template match="album" mode="pass2">
      <album>
       <album_num>
            <xsl:apply-templates select="*/*[1]" mode="pass2"/>
        </album_num>
      </album>
     </xsl:template>

     <xsl:template match="album_num/*" mode="pass2">
      <xsl:copy>
       <xsl:copy-of select="self::*[not(*)]/text()|key('kAlbumByChildName', name())/*/*/*"/>
      </xsl:copy>
     </xsl:template>
</xsl:stylesheet>

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

<t>
    <album>
        <album_num>hi.hello</album_num>
        <album_name>Cocktail</album_name>
    </album>
    <album>
        <album_num>hey.hello</album_num>
        <album_name>Mocktail</album_name>
    </album>
    <album>
        <album_num>hey.mello</album_num>
        <album_name>Monkeytail</album_name>
    </album>
    <album>
        <album_num>hey.yellow</album_num>
        <album_name>Donkeytail</album_name>
    </album>
    <album>
        <album_num>swallow</album_num>
        <album_name>abc</album_name>
    </album>
</t>

произвежда новия търсен резултат:

<album>
   <album_num>
      <hi>
         <hello>Cocktail</hello>
      </hi>
   </album_num>
</album>
<album>
   <album_num>
      <hey>
         <hello>Mocktail</hello>
         <mello>Monkeytail</mello>
         <yellow>Donkeytail</yellow>
      </hey>
   </album_num>
</album>
<album>
   <album_num>
      <swallow>abc</swallow>
   </album_num>
</album>
- person Control; 25.01.2012