tags:

views:

82

answers:

2

I have a xml file as below, and now I want to use the XSLT to transformer it, keep all the elements and attributes, but if it happen to the attributes with the value started with "SQL:", then execute the sql and replace the attribute value with the resolved SQL(it involve the http://msdn.microsoft.com/en-us/library/533texsx(VS.90).aspx. now I encoutered the issue:how to check if the current node type is attribute, and how to replace the attribute value, I base on the visual studio default template as below:

the example xml file(there are many elements in real):

<DM>
  <DV  id="SQL:Select something from db">
    <Sample aid="SQL:Select something from db">

    </Sample>
  </DV>
  <DV  id="SQL:Select something from db">
    <Sample aid="SQL:Select something from db">
    </Sample>
  </DV>
</DM>

default xslt:

<?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:ms="urn:schemas-microsoft-com:xslt" >
  <xsl:output method="xml" indent="yes"/>

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

Well, you're using one template to match both nodes and attributes. It would be easier to distinguish between them using two separate templates:

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

<!-- Another template for attributes -->
<xsl:template match="@*">
  <!-- Special case for SQL attributes goes here -->
</xsl:template>

To determine if a string starts with a particular substring, you'll want to use the starts-with() function. You can use it like this:

<xsl:if test="starts-with(.,'SQL:')">
  <!-- The current node starts with "SQL:" -->
</xsl:if>
Welbog
Cool, but I still do not know how to copy the Attribute's name, can you give example to copy the attribute's name and replace the value with a static test? thanks very much!
Leonard
<!-- Another template for attributes --> <xsl:template match="@*"> <!-- Special case for SQL attributes goes here --> <xsl:if test="starts-with(.,'SQL:')"> <xsl:attribute name="{name()}"> <xsl:text>asfsadf</xsl:text> </xsl:attribute> <!-- The current node starts with "SQL:" --> </xsl:if> </xsl:template>
Leonard
now it seems like I just can use the <xsl:attribute name="{name()}"> to "Copy". Thanks very much.
Leonard
@Welbog: It is not necessary to break the "indentity transform". What would you do if you need to process other attribute in special way? More `xsl:if`?
Alejandro
+2  A: 

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*[starts-with(translate(substring(.,1,4),'sql','SQL'),'SQL:')]">
        <xsl:attribute name="{name()}">
            <xsl:value-of select="'From SQL!'"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Result:

<DM>
    <DV id="From SQL!">
        <Sample aid="From SQL!"></Sample>
    </DV>
    <DV id="From SQL!">
        <Sample aid="From SQL!"></Sample>
    </DV>
</DM>

Note: Don't need to break "identity transform". Add attributes to result tree with xsl:attribute.

Alejandro