תשובה XML Space Issue

  • 24 เมษายน 2555 9:39
     
     

    I am having an issue with XML, I am reading a range of data from Excel and applying GetXML method to get the XML(using ODBC); now on the temp XML I have got, I am applying XSL to get that into a proper XML. The issue here is, for certain nodes, I am getting XML Space Preserve eg: <Middle xml:space="preserve"></Middle>; I am using XSLT 1.0; I want to know if there is a way that I can remove all of the space attribute from all nodes in the XML using XSL, please help. Thanks. I tried applying normalize-space and it works, but there are lot of elements that I am getting and it would be difficult to write this for all.


    Rpaul

ตอบทั้งหมด

  • 24 เมษายน 2555 10:13
     
     

    It depends on the XSLT approach you use, with template based XSLT it is easy e.g.

    <xsl:template match="@* | node()">

      <xsl:copy>

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

      </xsl:copy>

    </xsl:template>

    <xsl:template match="@xml:space"/>

    suffice to remove all xml:space attributes and copy everything unchanged. And you can now add templates for further transformation e.g.

      <xsl:element name="foo">

         <bar>

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

        </bar>

      </xsl:template>

    added transforms "foo" into "bar" element.


    MVP Data Platform Development My blog

  • 24 เมษายน 2555 10:23
     
     

    Hi Martin,

    Thanks for the quick reply, here is my sample XSL:

    <

    xsl:template match="/"><xsl:choose>

    <

    xsl:when test="$ParamPartnerKeyName=''">

    <

    Return><xsl:call-template name="ProcessK1"/></Return></xsl:when><xsl:otherwise><xsl:call-template name="ProcessK1"/></xsl:otherwise></xsl:choose></xsl:template><xsl:template name="ProcessK1"><xsl:for-each select="XmlContent/MNDataRegister/NewDataSet/Table"><xsl:variable name="RecordNo"><xsl:value-of select="position()"/></xsl:variable><xsl:variable name="PartnerKeyId"><xsl:value-of select="Partner_x0020_Key_x0020_Id"/></xsl:variable> - Will I be able to modify this? I am not sure on this. could you please help? Thanks.

    Rpaul

  • 24 เมษายน 2555 13:40
     
     

    Hi Martin,

    Also, this is an extract on how I am calling the XSL:

    //read XML

    TextReader tr1 = new StringReader(xml);

    XPathDocument xPathDocument = new XPathDocument(tr11);

    //read XSLT

    XmlTextReader tr22 = new XmlTextReader(Application.StartupPath + PathClient);

    XslCompiledTransform xslt = new XslCompiledTransform();

    xslt.Load(tr22,

    null, new MyXslUrlResolver());Can I handle that scenario here if not in XSL?


    Rpaul

  • 24 เมษายน 2555 15:21
     
     

    Can you repost your XSLT code so that it is readable?

    And you might want to show us a sample input and the corresponding output you want to create with XSLT, then we might be able to suggest a different approach with applying templates and matching templates instead of the procedural call template and for-each approach you currently have. That way we should be able to incorporate my previous suggestion to eliminate the xml:space attributes.


    MVP Data Platform Development My blog

  • 25 เมษายน 2555 13:40
     
     

    Hi Martin,

    Thanks for replying, My XSL is little complicated and big, so I may not be able to share the entire file, but here is the extract from the file - Thanks.

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
                    xmlns:exsl="http://exslt.org/common"
                    extension-element-prefixes="exsl"
    >
      <xsl:include href="K1Functions.xsl"/>
      <xsl:output method="xml" indent="yes"/> 
      <xsl:param name="ParamPartnerKeyName" select="''"/>
     
     
      <xsl:template match="/">
        <xsl:choose>
          <xsl:when test="$ParamPartnerKeyName=''">      
            <Return>
              <xsl:call-template name="ProcessK1"/>
            </Return>
          </xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="ProcessK1"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>

      <xsl:template name="ProcessK1">
        <xsl:for-each select="XmlContent/IDDataRegister/NewDataSet/Table">
          <xsl:variable name="RecordNo">
            <xsl:value-of select="position()"/>
          </xsl:variable>

          <xsl:variable name="PartnerKeyId">
            <xsl:value-of select="Partner_x0020_Key_x0020_ID"/>
          </xsl:variable>

          <xsl:variable name="PartnerKeyName">
            <xsl:value-of select="//XmlContent/PartnerInformationRegister/NewDataSet/Table[Partner_x0020_Key_x0020_Id = $PartnerKeyId]/Name_x0020_Line_x0020__x0023_1"/>
          </xsl:variable>


    Rpaul

  • 25 เมษายน 2555 13:57
     
     

    So you have a named template "ProcessK1" that you call, in that template you do a for-each over the node set XmlContent/IDDataRegister/NewDataSet/Table and you cross reference corresponding XmlContent/PartnerInformationRegister/NewDataSet/Table elements. That snippet does not show me any elements you copy or modify that could have xml:space attributes so I am not sure what to suggest, other than maybe chaining two stylesheets, where the first does your current transformation and where the second then uses my original suggestion to remove all xml:space attributes. Is that an option? With XslCompiledTransform to chain two stylesheets you could use a System.Xml.XmlDocument as an intermediary result, with code along the lines of e.g

    XmlDocument tempDoc = new XmlDocument();

    using (XmlWriter xw = tempDoc.CreateNavigator().AppendChild())

    {

      xslt.Transform(input, null, xw);

      xw.Close();

    }

    // now here you can apply the second stylesheet e.g.

    xslt2.Transform(tempDoc, null, resultStreamOrTextWriterOrXmlWriter);


    MVP Data Platform Development My blog

  • 26 เมษายน 2555 12:42
     
     

    Hi Martin,

    Thanks for the reply, adding to my snippet above, I am having something like shown  below - so in this the element "_x0034__x003A__x0020_Total_x0020_Everywhere" comes with the space preserve and it is causing problems. I tried normalize-space and it worked, but the problem is, the space attribute comes with lot of elements and I am not sure what to do, but I will try your earlier suggestions as well.

    <!--PropInventories Ending Col T -->
    <xsl:choose>          
    <xsl:when test="_x0034__x003A__x0020_Total_x0020_Everywhere != ''">
    <EOYAll>
     <xsl:value-of select="_x0034__x003A__x0020_Total_x0020_Everywhere"/>
    </EOYAll>
    </xsl:when>             
    </xsl:choose>


    Rpaul

  • 26 เมษายน 2555 17:35
     
     คำตอบ

    So you have input elements with xml:space="preserve" and you want to normalize the space in those elements? My first suggestion does not do that, instead it removes any xml:space attributes. If you want to normalize the spaces in any elements having that attribute then do e.g.

    <xsl:template match="@* | node()">

      <xsl:copy>

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

      </xsl:copy>

    </xsl:template>

    <xsl:template match="*[@xml:space = 'preserve']">

      <xsl:copy>

        <xsl:value-of select="normalize-space()"/>

      </xsl:copy>

    </xsl:template>

    Run that as a separation transformation step as suggested earlier.


    MVP Data Platform Development My blog

    • ทำเครื่องหมายเป็นคำตอบโดย Alan_chenModerator 7 พฤษภาคม 2555 7:08
    •  
  • 18 พฤษภาคม 2555 4:52
     
     

    Hi Martin,

    I have another issue with space and I am not sure what I can do, for a single element, I need to read a lot of column values into it.

    Eg: <Test>Desc1 Val1 Desc 2 Val2 Desc 3 Val3</Test> and it will go on, the problem is I am adding a space with <xsl:text> between each of the column values in the XSL(there are about 100 columns that I need to add into this single element in this format); the problem is - say the Val 1 is not there, then I will be adding only Val2 Desc2, since I am adding a space before I process each value, a leading space gets added and it is creating a validation error, could you please let me know on how to avoid this please? The space should be added between each of the values but when a column is not there then that should not add a leading space or after I process this in the XSL then the space can be removed at the end as well but not sure if this is possible in XSL, it is for only a single element. This is bit critical for me.


    Rpaul