Altova Mailing List Archives>Archive Index >microsoft.public.xsl Archive Home >Recent entries >Thread Prev - Re: Combining elements >Thread Next - Re: Combining elements Re: Combining elementsTo: NULL Date: 4/1/2008 10:32:00 AM
"Martin Honnen" <mahotrash@y...> wrote in message
news:eoQPgH$kIHA.6032@T......
> tshad wrote:
>
>>
>> What I would like the result to look like is:
>> ************************************************************
>> <?xml version="1.0" encoding="utf-8"?>
>> <REPORT>
>> <form>
>> <sectionNumber>0</sectionNumber>
>> <primary>True</primary>
>> <formName>1004</formName>
>> <tagName>OTHERFILENUMBER</tagName>
>> <flags>0</flags>
>> <format>0</format>
>> <value>692</value>
>> </form>
>> <form>
>> <sectionNumber>0</sectionNumber>
>> <primary>True</primary>
>> <formName>1004</formName>
>> <tagName>FNMA_FILENUMBER</tagName>
>> <flags>0</flags>
>> <format>0</format>
>> <value>693</value>
>> </form>
>> <form>
>> <sectionNumber>0</sectionNumber>
>> <primary>True</primary>
>> <formName>1004</formName>
>> <tagName>SUBPROPADDRESS</tagName>
>> <flags>0</flags>
>> <format>0</format>
>> <value>3</value>
>> </form>
>> <form>
>> <sectionNumber>0</sectionNumber>
>> <primary>True</primary>
>> <formName>1004</formName>
>> <tagName>SCMCOMMENTS_1</tagName>
>> <flags>0</flags>
>> <format>0</format>
>> <value>This is a test line 1 This is a test line 2 This is a test
>> line 3 This is a test line 4</value>
>> </form>
>> <form>
>> <sectionNumber>1</sectionNumber>
>> <primary>True</primary>
>> <formName>1004</formName>
>> <tagName>FormFormats</tagName>
>> <flags>0</flags>
>> <format>0</format>
>> <value>NUM=1 FORMCODE=1004 SECCODE=1 DESC= MAJOR=True</value>
>> </form>
>> </REPORT>
>
> Here is an adapted stylesheet that creates the output described above:
>
> <xsl:stylesheet
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>
> <xsl:output method="xml" indent="yes"/>
>
> <xsl:template match="REPORT">
> <xsl:copy>
> <xsl:apply-templates
> select="FORMS/FORM/FIELDS/*[not(starts-with(name(), 'SCMCOMMENTS'))]"/>
> <form>
> <sectionNumber>0</sectionNumber>
> <primary>True</primary>
> <formName><xsl:value-of select="FORMS/FORM/@FORMCODE"/></formName>
> <tagName>SCMCOMMENTS_1</tagName>
> <flags>0</flags>
> <format>0</format>
> <value>
> <xsl:apply-templates select="FORMS/FORM/FIELDS/*[starts-with(name(),
> 'SCMCOMMENTS')]"/>
> </value>
> </form>
> <form>
> <sectionNumber>
> <xsl:value-of select="FORMS/FORM/@SECCODE"/>
> </sectionNumber>
> <primary>True</primary>
> <formName>
> <xsl:value-of select="FORMS/FORM/@FORMCODE"/>
> </formName>
> <tagName>FormFormats</tagName>
> <flags>0</flags>
> <format>0</format>
> <value>
> <xsl:apply-templates select="FORMS/FORM/@*"/>
> </value>
> </form>
> <xsl:apply-templates select="FORMS/FORM/attachments/attachment"/>
> </xsl:copy>
> </xsl:template>
>
> <xsl:template match="FIELDS/*[not(starts-with(name(), 'SCMCOMMENTS'))]">
> <form>
> <sectionNumber>
> <xsl:text>0</xsl:text>
> </sectionNumber>
> <primary>True</primary>
> <formName>
> <xsl:value-of select="../../@FORMCODE"/>
> </formName>
> <tagName>
> <xsl:value-of select="name()"/>
> </tagName>
> <flags>0</flags>
> <format>0</format>
> <value>
> <xsl:value-of select="."/>
> </value>
> </form>
> </xsl:template>
>
> <xsl:template match="FIELDS/*[starts-with(name(), 'SCMCOMMENTS')]">
> <xsl:value-of select="."/>
> <xsl:if test="position() != last()">
> <xsl:text> </xsl:text>
> </xsl:if>
> </xsl:template>
>
> <xsl:template match="FORM/@*">
> <xsl:value-of select="concat(name(), '=', .)"/>
> <xsl:if test="position() != last()">
> <xsl:text> </xsl:text>
> </xsl:if>
> </xsl:template>
>
> </xsl:stylesheet>
>
>
This works perfect.
I am just not sure I understand why. as normally we don't do anything in the
first template except apply the next templates. This has always been a
confusion with me on how the different templates work. I got a better idea
when we did the concat of the attributes and put the apply-templates inside
the 2nd template.
In all my other ones, I always used the 1st template to apply the other
templates, but did nothing in it.
This one is different.
I'll take a stab at what I think it is doing.
1) We get all the elements in the page. Since REPORT is the first element -
we get that and all below it. We could also have done "/*", I believe - not
sure about "/".
2) Not sure what the xsl:copy does, but then we apply-template that looks
similar to "FORMS/FORM/FIELDS/*[not(starts-with(name(), 'SCMCOMMENTS'))]".
The template actually is "FIELDS/*[not(starts-with(name(), 'SCMCOMMENTS'))]"
which gets all the elements that don't start with SCMCOMMENTS and applys the
template to each of those fields. Not sure why the one has FORMS/FORM/ in
front of it and the other doesn't.
3) Then we do one element set that starts with SCMCOMMENTS and for the value
we apply the template that looks like:
FORMS/FORM/FIELDS/*[starts-with(name(), 'SCMCOMMENTS')], but doesn't have
the FORMS/FORM/ in front and we keep adding them together with a blank at
the end - if not the last one.
4) Then we do one set that concatenates the attributes of the FORM element
together.
5) Lastly, we apply the attachment elements (which we don't have in this xml
file) but does work fine in the finished one.
This works fine with one set of comments, but is there a way to change the
"FIELDS/*[not(starts-with(name(), 'SCMCOMMENTS'))]" to something that looks
at multiple sets of comments. For example, if we had a file that looked
something like:
The sample xml file looks like:
*********************************************************
<?xml version="1.0" encoding="utf-8"?>
<REPORT VERSION="1.10" FILENUM="" DESCRIPTION="Form Utility XML: 3/18/2008
12:27:13 PM" MAJORFORM="1004">
<FORMS>
<FORM NUM="1" FORMCODE="1004" SECCODE="1" DESC="" MAJOR="True" >
<FIELDS>
<OTHERFILENUMBER>692</OTHERFILENUMBER>
<FNMA_FILENUMBER>693</FNMA_FILENUMBER>
<SUBPROPADDRESS>3</SUBPROPADDRESS>
<SCMCOMMENTS_1>This is a test line 1</SCMCOMMENTS_1>
<SCMCOMMENTS_2>This is a test line 2</SCMCOMMENTS_2>
<SCMCOMMENTS_3>This is a test line 3</SCMCOMMENTS_3>
<SCMCOMMENTS_4>This is a test line 4</SCMCOMMENTS_4>
<GEN_COMMENTS_1>Testing line 1</GEN_COMMENTS_1>
<GEN_COMMENTS_2>Testing line 2</GEN_COMMENTS_2>
<GEN_COMMENTS_3>Testing line 3</GEN_COMMENTS_3>
<GEN_COMMENTS_4>Testing line 4</GEN_COMMENTS_4>
<CMPHIST_TXT>The test line1</CMPHIST_TXT>
<CMPHIST_TXT2 >The test line1</CMPHIST_TXT2>
<CMPHIST_TXT3 >The test line1</CMPHIST_TXT3>
<CMPHIST_TXT4 >The test line1</CMPHIST_TXT4>
</FIELDS>
</FORM>
</FORMS>
</REPORT>
*********************************************************
Could we change the select statements to something like:
FIELDS/*[not(starts-with(name(), 'SCMCOMMENTS')) & not(starts-with(name(),
'GEN_COMMENTS')) & not(starts-with(name(), 'CMPHIST_TXT')) ]"
and then set up different templates for each.
Or do some type of contains that compares multiple strings?
Thanks,
Tom
> --
>
> Martin Honnen --- MVP XML
> http://JavaScript.FAQTs.com/
| ||||||
| Company | Legal | Press | Partners | Careers | Sitemap | Contact Us | Altova Blog | Mobile | Full Site | |||
|
