Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

This is my original XML file:

<?xml version="1.0" encoding="windows-1250"?>
<CONTACTS>
    <CONTACT>
        <FirstName>Arun</FirstName>
        <LastName>Arun_niit</LastName>
        <EMail>[email protected]</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>Arun</FirstName>
        <LastName>Arun_niit</LastName>
        <EMail>[email protected]</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>KumarVeera</FirstName>
        <LastName>Veera Kumar</LastName>
        <EMail>[email protected]</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>MarbellaFunkybuddha</FirstName>
        <LastName>Funkybuddha Marbella</LastName>
        <URL>http://www.facebook.com/profile.php?id=111123301493096451</URL>
    </CONTACT>
    <CONTACT>
        <FirstName>Rangarajkarthik</FirstName>
        <LastName>karthik Rangaraj</LastName>
        <EMail>[email protected]</EMail>
        <EMail>[email protected]</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>Rangaraj</FirstName>
        <LastName>karthik </LastName>
        <EMail>[email protected]</EMail>
        <EMail>[email protected]</EMail>
    </CONTACT>
</CONTACTS>

I have 4 XSl files which is working perfectly if I execute one by one using XSLT processor in Firefox XUL. When I execute all the XSL files one by one simultaneously it's not generating the final output.

This the actual output of the above XML file if I use the XSL files one by one:

<?xml version="1.0" encoding="UTF-8"?>
<CONTACTS>
<CONTACT>
<CUS-ID>PDE-ID2</CUS-ID>
<FirstName>Arun</FirstName>
<LastName>Arun_niit</LastName>
<gmail>[email protected]</gmail>
<yahoo>[email protected]</yahoo>

<URL/>
<Facebook-ID/>
</CONTACT>
<CONTACT>
<CUS-ID>PDE-ID4</CUS-ID>
<FirstName>KumarVeera</FirstName>
<LastName>Veera Kumar</LastName>
<gmail/>
<yahoo>[email protected]</yahoo>

<URL/>
<Facebook-ID/>
</CONTACT>
<CONTACT>
<CUS-ID>PDE-ID6</CUS-ID>
<FirstName>MarbellaFunkybuddha</FirstName>
<LastName>Funkybuddha Marbella</LastName>
<gmail/>
<yahoo/>

<URL>http://www.facebook.com/profile.php?id=111123301493096451</URL>
<Facebook-ID>1123301493096451</Facebook-ID>
</CONTACT>
<CONTACT>
<CUS-ID>PDE-ID12</CUS-ID>
<FirstName>Rangarajkarthik</FirstName>
<LastName>karthik Rangaraj</LastName>
<gmail>[email protected]</gmail>
<yahoo>[email protected]</yahoo>
<URL/>
<Facebook-ID/>
</CONTACT>
</CONTACTS>

This is the actual JS function to call the XSl file in XUL:

function process()
{
    var src = readFile("D:\\createXML2.xsl");
    var parsed = (new DOMParser()).parseFromString(src, "text/xml");
    var stylesheet = parsed.documentElement;

    var processor = new XSLTProcessor();
    processor.importStylesheet(stylesheet );

    objXMLDoc = processor.transformToDocument(objXMLDoc);


    var serializer = new XMLSerializer();
    var prettyString = serializer.serializeToString(objXMLDoc);

    saveFile(prettyString, "D:\\aout30.xml");
     //alert('New Contact updated successfully');


      var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                            .getService(Components.interfaces.nsIPromptService);

       prompts.alert(null, "Final creation", "Final creation is done");
process2();
}

These are the XSL files I'm using to generate my final output:

File1: To merge contacts with the same FN & LN

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

<xsl:key name="groupName" match="//CONTACTS/CONTACT" use="concat(FirstName, LastName)" />

<xsl:template match="CONTACTS">

  <CONTACTS>
  <xsl:for-each select="//CONTACTS/CONTACT[generate-id() = generate-id( key('groupName', concat(FirstName, LastName))   [1] ) ]" >
    <xsl:sort select="CONTACT/EMail"  />

      <xsl:call-template name="group">
        <xsl:with-param name="k1" select="FirstName" />
        <xsl:with-param name="k2" select="LastName" />
      </xsl:call-template>

  </xsl:for-each>
  </CONTACTS>
</xsl:template> 

<xsl:template name="group">
<xsl:param name="k1" /> 
<xsl:param name="k2" /> 

  <CONTACT>
  <xsl:for-each select="//CONTACTS/CONTACT[FirstName = $k1][LastName = $k2][1]">

    <xsl:copy-of select="FirstName" />       
    <xsl:copy-of select="LastName" />       
    <!-- here we have the first Email -->
    <xsl:copy-of select="EMail" />       

  </xsl:for-each>
  <xsl:for-each select="//CONTACTS/CONTACT[FirstName = $k1][LastName = $k2][position() &gt; 1]">
    <!-- here we have the next Email -->

    <xsl:copy-of select="EMail" />       

  </xsl:for-each>

    <xsl:for-each select="//CONTACTS/CONTACT[FirstName = $k1][LastName = $k2][position() &gt; 2]">
    <!-- here we have the next Email -->

    <xsl:copy-of select="EMail" />       

  </xsl:for-each>

      <xsl:for-each select="//CONTACTS/CONTACT[FirstName = $k1][LastName = $k2][position() &gt; 3]">
    <!-- here we have the next Email -->

    <xsl:copy-of select="EMail" />       

  </xsl:for-each>

    <xsl:copy-of select="URL" />       

  </CONTACT>

</xsl:template> 
</xsl:stylesheet>

File2: To merge same email address of different contacts

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

    <xsl:key name="k_ContactsByEmail"
        match="CONTACTS/CONTACT"
        use="EMail"/>

    <xsl:template match="CONTACTS">
        <xsl:copy>
            <xsl:apply-templates select="CONTACT[generate-id()=
                generate-id(key('k_ContactsByEmail',EMail)[1])]
                |
                CONTACT[not(EMail)]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="CONTACT">
        <xsl:copy>
            <xsl:copy-of select="*"/>
            <xsl:copy-of select="
                key('k_ContactsByEmail', EMail)/*
                    [not(.=current()/*)]
                    [not(self::FirstName or self::LastName)]"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

File 3: File 3 to separate the email values according to domain type

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

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="CONTACT">
        <xsl:copy>

              <xsl:copy-of select="FirstName|LastName|URL"/>
             <Facebook-ID><!-- To extract the ID value from URL/Email -->
            <xsl:choose>
                <xsl:when test="URL">
                    <xsl:value-of select="substring-after(URL,'?id=')"/>
                </xsl:when>
                <xsl:otherwise>
                   <!-- <xsl:value-of select="substring-before(EMail[1],'@')"/>-->
                </xsl:otherwise>
            </xsl:choose>
        </Facebook-ID>
            <EMAILS>
                <xsl:apply-templates select="EMail"/>
            </EMAILS>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="EMail">
        <EMail> <!-- To extract the Emails based on domain value from EMAIL -->
            <Type><xsl:value-of select="substring-before(
                    substring-after(.,'@'),
                    '.')"/>
            </Type>
            <Value><xsl:value-of select="."/></Value>
        </EMail>
    </xsl:template>

</xsl:stylesheet>

File 4: Generate cutomer ID for each contact and add the email domain tag to the email values type from the 3rd xsl generated output file.

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


<!--Identity template to copy content forward-->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="CONTACT">
<xsl:copy>

<CUS-ID>
    <xsl:apply-templates select="." mode="generate-id"/>
    </CUS-ID>


    <FirstName>
        <xsl:value-of select="FirstName"/>
    </FirstName>

    <LastName>
        <xsl:value-of select="LastName"/>
    </LastName>

    <gmail>
            <xsl:value-of select="EMAILS/EMail[Type='gmail']/Value"/>
    </gmail>

    <yahoo>
            <xsl:value-of select="EMAILS/EMail[Type='yahoo']/Value"/>
    </yahoo>


    <URL>
            <xsl:value-of select="URL"/>
    </URL>

    <Facebook-ID>
             <xsl:value-of select="Facebook-ID"/>
    </Facebook-ID>

      </xsl:copy>
</xsl:template>

<xsl:template match="node()" mode="generate-id">
            <xsl:text>PDE-ID</xsl:text>
            <xsl:number level="any" count="node()" format="10000"/> 
</xsl:template>

</xsl:stylesheet>

Sometimes it's generating the proper output but most of the time it's not working. I really don't understand what could be the problem. Is there any possibility to combine all these SL files as a single file? Please help me. Thank you.

share|improve this question
    
What exactly happens when it's "not working"? From your JS code I understand that you have 3 intermediate results and the final result. I guess that "one by one simultaneously" means you remove the alert() call. Do you see any messages in the Error Console and/or do you notice any problems with the intermediate results? What do readFile() and saveFile() look like? What happens if you log the string you read from the files with the intermediate results? –  Nickolay Sep 4 '11 at 5:07
    
@Nickolay : Generally the readFile() & saveFile() are javascript functions to read the XSL files and Save the XML file as prettyString suggested by Firefox. What happens sometime, any one of the XSL file didn't give the proper output so the next XSL file won't work exactly. There won't be error in the Firefox error console. Is there any way to combine all these XSL file as as single file? –  linguini Sep 4 '11 at 7:49

1 Answer 1

up vote 1 down vote accepted

To combine the transforms shown above you would need a node-set() extension function, which is probably not available from your javascript library (is it?).

However, at least for the input sample shown above (slightly changed to cover other cases), I think it is possible to perform all of your tasks with a single transform.

Note your solution (and this one too) does not handle Facebook-ID generated element when URL node is in the duplicate CONTACT.

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

    <xsl:key name="k_Name" match="CONTACTS/CONTACT" 
        use="concat(FirstName, LastName)" />
    <xsl:key name="k_Email" match="CONTACTS/CONTACT" 
        use="EMail" />

    <xsl:template match="CONTACTS">
        <xsl:copy>
            <xsl:apply-templates select="
                CONTACT[generate-id()
                = generate-id(key('k_Email',EMail)[1])
                and generate-id()
                = generate-id(key('k_Name',concat(FirstName,LastName))[1])]
                |
                CONTACT[not(EMail)]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="CONTACT">
        <xsl:copy>

            <CUS-ID>
                <xsl:apply-templates select="." mode="generate-id"/>
            </CUS-ID>

            <xsl:copy-of select="FirstName|LastName"/>

            <Facebook-ID><!-- To extract the ID value from URL/Email -->
                <xsl:choose>
                    <xsl:when test="URL">
                        <xsl:value-of select="substring-after(URL,'?id=')"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <!-- <xsl:value-of select="substring-before(EMail[1],'@')"/>-->
                    </xsl:otherwise>
                </xsl:choose>
            </Facebook-ID>

            <xsl:apply-templates select="
                (*
                |
                key('k_Email', EMail)/*
                [not(.=current()/*)]
                |
                key('k_Name',concat(FirstName,LastName))/*
                [not(.=current()/*)])
                [not(self::FirstName or self::LastName)]"/>
        </xsl:copy> 
    </xsl:template>

    <xsl:template match="URL">
        <xsl:copy-of select="."/>
    </xsl:template>

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


    <xsl:template match="node()" mode="generate-id">
        <xsl:text>PDE-ID</xsl:text>
        <xsl:number level="any" count="node()" format="10000"/> 
    </xsl:template>

</xsl:stylesheet>

When applied on the following input:

<CONTACTS>
    <CONTACT>
        <FirstName>Arun</FirstName>
        <LastName>Arun_niit</LastName>
        <EMail>[email protected]</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>Arun</FirstName>
                <LastName>Arun_niit</LastName>
                <URL>aaa</URL>
        <EMail>[email protected]</EMail>
        <EMail>[email protected]</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>KumarVeera</FirstName>
        <LastName>Veera Kumar</LastName>
        <EMail>[email protected]</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>MarbellaFunkybuddha</FirstName>
        <LastName>Funkybuddha Marbella</LastName>
        <URL>http://www.facebook.com/profile.php?id=111123301493096451</URL>
    </CONTACT>
    <CONTACT>
        <FirstName>Rangarajkarthik</FirstName>
        <LastName>karthik Rangaraj</LastName>
        <EMail>[email protected]</EMail>
        <EMail>[email protected]</EMail>
    </CONTACT>
    <CONTACT>
        <FirstName>Rangaraj</FirstName>
        <LastName>karthik </LastName>
        <EMail>[email protected]</EMail>
        <EMail>[email protected]</EMail>
    </CONTACT>
</CONTACTS>

produces:

<CONTACTS>
   <CONTACT>
      <CUS-ID>PDE-ID00002</CUS-ID>
      <FirstName>Arun</FirstName>
      <LastName>Arun_niit</LastName>
      <Facebook-ID/>
      <yahoo>[email protected]</yahoo>
      <URL>aaa</URL>
      <gmail>[email protected]</gmail>
      <gmai>[email protected]</gmai>
   </CONTACT>
   <CONTACT>
      <CUS-ID>PDE-ID00020</CUS-ID>
      <FirstName>KumarVeera</FirstName>
      <LastName>Veera Kumar</LastName>
      <Facebook-ID/>
      <yahoo>[email protected]</yahoo>
   </CONTACT>
   <CONTACT>
      <CUS-ID>PDE-ID00027</CUS-ID>
      <FirstName>MarbellaFunkybuddha</FirstName>
      <LastName>Funkybuddha Marbella</LastName>
      <Facebook-ID>111123301493096451</Facebook-ID>
      <URL>http://www.facebook.com/profile.php?id=111123301493096451</URL>
   </CONTACT>
   <CONTACT>
      <CUS-ID>PDE-ID00034</CUS-ID>
      <FirstName>Rangarajkarthik</FirstName>
      <LastName>karthik Rangaraj</LastName>
      <Facebook-ID/>
      <gmail>[email protected]</gmail>
      <yahoo>[email protected]</yahoo>
   </CONTACT>
</CONTACTS>
share|improve this answer
    
:Well, I'm not evaluating any data during this process. My java-script function is to read the XML & XSL files and save the XSL generated XML file using XSLT processor in XUL. I have executed your XSL file in Eclipse, it works fine. When I checked in XUL XSLT processor it didn't generate the proper output.Finally, I have raised a bug in Mozilla Firefox. Thank you very much. –  linguini Sep 5 '11 at 10:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.