Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Process list of attributes in a node 1

Status
Not open for further replies.

tshad

Programmer
Jul 15, 2004
386
0
0
US
I need to process a list of unknown attributes in a node. Normally I would test if the attributes exist and process each one.

Now I have an instance where I know the node but not the attributes and I need to process them. They would be processed in exactly the same way except for the name and value of the attribute.

For example:

With this xml file:
Code:
<RESPONSE MISMOVersionID="2.6">
  <REPORT _ID="Major" MajorFormType="Form102">
    <FORM _ID="Minor" MinorFormType="Form240">
      <IMAGE _ID="Im2"/>
    </FORM>
  </REPORT>
  <METHODS Description="THIS IS SUMMARY">
    <COMPARISON ID="241" ComparisonAmount="352,000">
      <SALE SequenceId="0" state="true" saleDate="05/15/2011">
        <LOCATION Address="9107 Forest Ct" Address2="Franklin, CT"/>
        <ADJUSTMENT Type="Concessions" _Description="N/A"/>
      </SALE>
    </COMPARISON>
  </METHODS>
</RESPONSE>

I have the following xslt file:
Code:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL]
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="METHODS/COMPARISON/SALE">
        <xsl:with-param name="reportName" select="REPORT/@MajorFormType"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <!-- Now we handle the other sections after the DATA section -->

  <xsl:template match="SALE">
    <xsl:param name="reportName"/>
    <xsl:if test="@state">
      <form>
        <section>
          <xsl:value-of select="../@SequenceId"/>
        </section>
        <formName>
          <xsl:value-of select="$reportName"/>
        </formName>
        <tagName>
          <xsl:text>state</xsl:text>
        </tagName>
        <value>
          <xsl:value-of select="@state"/>
        </value>
      </form>
    </xsl:if>
    <xsl:if test="@saleDate">
      <form>
        <section>
          <xsl:value-of select="../@SequenceId"/>
        </section>
        <formName>
          <xsl:value-of select="$reportName"/>
        </formName>
        <tagName>
          <xsl:text>saleDate</xsl:text>
        </tagName>
        <value>
          <xsl:value-of select="@saleDate"/>
        </value>
      </form>
    </xsl:if>
    <xsl:apply-templates>
      <xsl:with-param name="reportName" select="$reportName"/>
    </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>

Here I know what the attributes are and get the following results:
Code:
<?xml version="1.0" encoding="utf-8"?>
<RESPONSE>
  <form>
    <section></section>
    <formName>Form102</formName>
    <tagName>state</tagName>
    <value>true</value>
  </form>
  <form>
    <section></section>
    <formName>Form102</formName>
    <tagName>saleDate</tagName>
    <value>05/15/2011</value>
  </form>
</RESPONSE>

Is there a way to process the attributes the same way without knowing what the attribute names are such that I would have the same resultes for each attribute with only the <tagName> having the name of the attribute and <value> having the value of the attribute?

Thanks,

Tom
 
You can use the attribute axis for that. (You have been using the child axis.)

Example

Tom Morrison
Micro Focus
 
How would I do that here?

I tried:

Code:
  <xsl:template match="SALE/@*">
    <xsl:value-of select ="."/>
  </xsl:template>

But that didn't work.

Thanks,

Tom
 
Hi Tom,

Not knowing (1) what context that template was used in and (2) how it did not work make it a bit difficult to diagnose what might be happening. You may not be doing anything to cause the template to match, for example.

In general, from a template matching SALE you would want to <xsl:apply-templates select="@*"/>.

The have a template that matches attributes:
Code:
<xsl:template match="@*">
  <form>
    <section>
   [i] etc etc [/i]
    <tagName><xsl:value-of select="local-name()"/></tagName>
    <value><xsl:value-of select="."/></value>
  </form>
</xsl:template>

Still using Visual Studio 2010 for debugging? There are better XSLT debugging tools on the market...

Tom Morrison
Micro Focus
 
That might work for me.

I had actually tried a couple of things and found one that worked - not sure which is better:

Code:
  <xsl:template match="SALE">
    <xsl:param name="reportName"/>
    <xsl:for-each select="@*">
        <form>
            <section>
                <xsl:value-of select="../@SequenceId"/>
            </section>        
            <formName>
                <xsl:value-of select="$reportName"/>
            </formName>
            <tagName>
                <xsl:value-of select="name()"/>
            </tagName>
            <value>
                <xsl:value-of select="."/>
            </value>
        </form>
    </xsl:for-each>
    <xsl:if test="@state">

Yes, I am still using VS 2010 for debugging as it works for what I need. I was looking for a better one years ago and they all seemed to be pretty expensive.

Tom
 
This is fine. Iterating in a for-each is not approved by some purists, who prefer the template match when it works, but I think a for-each does fine here.

Tom Morrison
Micro Focus
 
I didn't know how to use a match for attributes here so that was why I used it.

Thanks,

Tom
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top