Extend XML file attributes using XSLT

  • Thread starter =?iso-8859-1?q?Christian_R=FChl?=
  • Start date
?

=?iso-8859-1?q?Christian_R=FChl?=

Hi folks!

I have a little noob problem here with XSLT. I have a XML file that
looks like this:

<archiveFiles>
<module path="c:/temp/module_m17_blabla.tmp"/>
<module path="c:/temp/module_m34_blabla.tmp"/>
...
<moduleAddition path="c:/temp/moduleaddition_m17.tmp"/>
...
</archiveFiles>

What I want to do now is the following:

1.) Copy name part of filename in <module>
---------------------------------------------
I want to copy that module name part and add it to a new attribute
called "name". How should I do this? The name of each module comes
right after module_ in the path-attributes.

2.) Reference additional information to these modules
---------------------------------------------
Finally another attribute "addition" should be added to each <module>
when there is a <moduleAddition> node with the same module name in its
"path" attribute. So that the outcome of the upper XML file looks like
this:

<archiveFiles>
<module name ="m17" path="c:/temp/module_m17_blabla.tmp"
additon="c:/temp/moduleaddition_m17.tmp"/>
<module name ="m34" path="c:/temp/module_m34_blabla.tmp"/>
...
</archiveFiles>

I really hope you can help me. I never worked with XSLT before and I
couldn't find the right hints and/or tutorials yet. :(

Thanks a lot in advance!

/Chris
 
P

Pavel Lepin

Christian Rühl said:
I have a little noob problem here with XSLT. I have a XML
file that looks like this:

<archiveFiles>
<module path="c:/temp/module_m17_blabla.tmp"/>
<module path="c:/temp/module_m34_blabla.tmp"/>
...
<moduleAddition path="c:/temp/moduleaddition_m17.tmp"/>
...
</archiveFiles>

As a rule of the thumb, string processing is not one of
XSLT's strong suits. XSLT2 is a bit better in that
department, but compliant processors are still rare.
Consider using a general-purpose language in tandem with
DOM or SAX parser.
I want to copy that module name part and add it to a new
attribute called "name". How should I do this? The name of
each module comes right after module_ in the
path-attributes.
substring-after()
substring-before()

Finally another attribute "addition" should be added to
each <module> when there is a <moduleAddition> node with
the same module name in its "path" attribute.

Define a key on moduleAddition elements. Use the identity
transformation. Define a couple of templates that match
moduleAddition elements - one of them excluding those nodes
from normal processing, the other generating the relevant
attribute. When processing module elements, invoke template
application to a nodeset consisting of appropriate
moduleAddition elements.

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="mod-add" match="moduleAddition"
use=
"
substring-before
(substring-after(@path,'moduleaddition_'),'.')
"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="module">
<xsl:variable name="name">
<xsl:call-template name="module-name"/>
</xsl:variable>
<xsl:copy>
<xsl:attribute name="name">
<xsl:value-of select="$name"/>
</xsl:attribute>
<xsl:apply-templates select="key('mod-add',$name)"
mode="add"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template name="module-name">
<xsl:value-of
select=
"
substring-before
(substring-after(@path,'module_'),'_')
"/>
</xsl:template>
<xsl:template match="moduleAddition"/>
<xsl:template match="moduleAddition" mode="add">
<xsl:attribute name="addition">
<xsl:value-of select="@path"/>
</xsl:attribute>
</xsl:template>
I really hope you can help me. I never worked with XSLT
before and I couldn't find the right hints and/or
tutorials yet. :(

XSLT FAQ and IBM's developerWorks section on XML are two
oft-mentioned resources, although both are not exactly
aimed at neophytes. Mozilla Developer Center has useful
references on XSLT and XPath, as well as some in-depth
materials. W3C's specs are priceless but might be hard to
parse.
 
?

=?iso-8859-1?q?Christian_R=FChl?=

As a rule of the thumb, string processing is not one of
XSLT's strong suits. XSLT2 is a bit better in that
department, but compliant processors are still rare.
Consider using a general-purpose language in tandem with
DOM or SAX parser.


Define a key on moduleAddition elements. Use the identity
transformation. Define a couple of templates that match
moduleAddition elements - one of them excluding those nodes
from normal processing, the other generating the relevant
attribute. When processing module elements, invoke template
application to a nodeset consisting of appropriate
moduleAddition elements.

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="mod-add" match="moduleAddition"
use=
"
substring-before
(substring-after(@path,'moduleaddition_'),'.')
"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="module">
<xsl:variable name="name">
<xsl:call-template name="module-name"/>
</xsl:variable>
<xsl:copy>
<xsl:attribute name="name">
<xsl:value-of select="$name"/>
</xsl:attribute>
<xsl:apply-templates select="key('mod-add',$name)"
mode="add"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template name="module-name">
<xsl:value-of
select=
"
substring-before
(substring-after(@path,'module_'),'_')
"/>
</xsl:template>
<xsl:template match="moduleAddition"/>
<xsl:template match="moduleAddition" mode="add">
<xsl:attribute name="addition">
<xsl:value-of select="@path"/>
</xsl:attribute>
</xsl:template>


XSLT FAQ and IBM's developerWorks section on XML are two
oft-mentioned resources, although both are not exactly
aimed at neophytes. Mozilla Developer Center has useful
references on XSLT and XPath, as well as some in-depth
materials. W3C's specs are priceless but might be hard to
parse.

Wow! Thanks a lot Pavel! That did the trick! Great! :)
 
C

Christian Rühl

new day, new problem here... :(

i have two xml files with some similar attributes. i want to copy
specific content (namely attributes) from one xml file to the other.

to show you of what i'm talking, heres how my archive and my product
tree xml files look like (very abstract):

--- archive.xml ---

<Common name="..." path="..." />
<Common ... />
<Glue name="..." path="..." />
<Glue ... />
<Mtds name="..." path="..." />
<Mtds ... />
<Mtds ... />
<ARCHIVE>
<Module moduleName="moduleA" variant="2" subsystem="subsystemA"
path="..." textConvention="..." />
<Module moduleName="moduleX" variant="17" subsystem="subsystemB"
path="..." textConvention="..." />
<Product cid="9000" subsystem="subsystemD" path="..."
textConvention="..." />
</ARCHIVE>

--- prodtree.xml ---

<PRODUCT_TREE productName="TestProduct" softwareVersion="1.0"
description="...">
<TopLevelComponent topLevelModule="Mab" cid="1200" description="...">
<Module selectedModule="moduleA" instance="12"/>
<Component topLevelModule="Mxy" cid="9000" description="...">
<SubComponent topLevelModule="Mxy" cid="5500" description="...">
<Module selectedModule="moduleX" instance="1"/>
</SubComponent>
</Component>
</TopLevelComponent>
</PRODUCT_TREE>

------------------------------------------
hint:
PRODUCT_TREE/selectedModule == ARCHIVE/moduleName
------------------------------------------

what i want to do now is to extend the prodtree.xml as said below:

- for all <*Component> nodes: check if there is a <Product> node in
archive.xml with the same cid? if so: copy all other attributes from
that node.
- for all <Module> nodes: check if there is a <Module> node in
archive.xml with the selectedModule == moduleName? if so: copy all
other attributes from that node.

so that the outcome looks like this:

--- result.xml ---

<PRODUCT_TREE productName="TestProduct" softwareVersion="1.0"
description="...">
<TopLevelComponent topLevelModule="Mab" cid="1200" description="...">
<Module selectedModule="moduleA" instance="12" variant="2"
subsystem="subsystemA" path="..." textConvention="..."/>
<Component topLevelModule="Mxy" cid="9000" subsystem="subsystemD"
path="..." description="...">
....
</PRODUCT_TREE>

------------------------------------------

i really hope you can help me again! thats how far i came by now:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:eek:utput method="xml" indent="yes"/>
<xsl:param name="archive"/>
<xsl:template match="/">
<TOP>
<xsl:for-each select="TopLevelComponent">
<TopLevelComponent cid="{@cid}"
topLevelModule="{@topLevelModule}"
softwareVersion="{@softwareVersion}">
<xsl:variable name="cid"
select="string(@cid)"/>
<xsl:for-each
select="document($archive)">
<xsl:copy-of
select="cid($cid)/*"/>
</xsl:for-each>
</TopLevelComponent>
</xsl:for-each>
</TOP>
</xsl:template>
</xsl:stylesheet>

doesn't work of course... :(
 
P

Pavel Lepin

Christian Rühl said:
to show you of what i'm talking, heres how my archive and
my product tree xml files look like (very abstract):

Right. Excellent idea. I thought last time I asked you why
didn't you post a real XML document that demonstrates your
problem? So you didn't get the hint?

Note that that doesn't parse to: "You should post your real
documents and code". Instead, it parses to: "You should
post smallest possible well-formed, valid documents and
code that demonstrate the problem you want to solve." This
is what is referred to as SSCCE on some newsgroups.
<Common name="..." path="..." />
<Common ... />
<Glue name="..." path="..." />
<Glue ... />
<Mtds name="..." path="..." />
<Mtds ... />
<Mtds ... />
<ARCHIVE>
<Module moduleName="moduleA" variant="2"
subsystem="subsystemA" path="..." textConvention="..." />
<Module moduleName="moduleX" variant="17"
subsystem="subsystemB" path="..." textConvention="..." />
<Product cid="9000" subsystem="subsystemD" path="..."
textConvention="..." />
</ARCHIVE>

Not well-formed in more ways than I care to list.
<PRODUCT_TREE productName="TestProduct"
softwareVersion="1.0" description="...">
<TopLevelComponent topLevelModule="Mab" cid="1200"
description="..."> <Module selectedModule="moduleA"
instance="12"/> <Component topLevelModule="Mxy" cid="9000"
description="..."> <SubComponent topLevelModule="Mxy"
cid="5500" description="..."> <Module
selectedModule="moduleX" instance="1"/> </SubComponent>
</Component>
</TopLevelComponent>
</PRODUCT_TREE>

PRODUCT_TREE/selectedModule

Doesn't make any sense to me. PRODUCT_TREE element doesn't
have any selectedModule element children.
== ARCHIVE/moduleName

Doesn't make any sense to me. ARCHIVE element doesn't have
any moduleName element children.

[snip requirements]

Please follow the link at the end of this post and read the
document located there. You seem to be under the false
impression that we're here to do your job for you, with no
compensation whatsoever. Can't say about other posters, but
I'm most certainly not.
<xsl:for-each select="TopLevelComponent">

Don't use xsl:for-each unless you understand what it is and
how it works.
<xsl:for-each select="document($archive)">

Gr-r-reat idea.
<xsl:copy-of select="cid($cid)/*"/>

Excellent indentation. Looks great when wrapped to 78
characters. if you don't want help, why don't you just say
so?

Oh, and there's no cid() function in XPath.

<http://www.catb.org/~esr/faqs/smart-questions.html>

NB: You're this >< short of being *plonk*ed.
 
C

Christian Rühl

to show you of what i'm talking, heres how my archive and
my product tree xml files look like (very abstract):

Right. Excellent idea. I thought last time I asked you why
didn't you post a real XML document that demonstrates your
problem? So you didn't get the hint?

Note that that doesn't parse to: "You should post your real
documents and code". Instead, it parses to: "You should
post smallest possible well-formed, valid documents and
code that demonstrate the problem you want to solve." This
is what is referred to as SSCCE on some newsgroups.
<Common name="..." path="..." />
<Common ... />
<Glue name="..." path="..." />
<Glue ... />
<Mtds name="..." path="..." />
<Mtds ... />
<Mtds ... />
<ARCHIVE>
<Module moduleName="moduleA" variant="2"
subsystem="subsystemA" path="..." textConvention="..." />
<Module moduleName="moduleX" variant="17"
subsystem="subsystemB" path="..." textConvention="..." />
<Product cid="9000" subsystem="subsystemD" path="..."
textConvention="..." />
</ARCHIVE>

Not well-formed in more ways than I care to list.
<PRODUCT_TREE productName="TestProduct"
softwareVersion="1.0" description="...">
<TopLevelComponent topLevelModule="Mab" cid="1200"
description="..."> <Module selectedModule="moduleA"
instance="12"/> <Component topLevelModule="Mxy" cid="9000"
description="..."> <SubComponent topLevelModule="Mxy"
cid="5500" description="..."> <Module
selectedModule="moduleX" instance="1"/> </SubComponent>
</Component>
</TopLevelComponent>
</PRODUCT_TREE>
PRODUCT_TREE/selectedModule

Doesn't make any sense to me. PRODUCT_TREE element doesn't
have any selectedModule element children.
== ARCHIVE/moduleName

Doesn't make any sense to me. ARCHIVE element doesn't have
any moduleName element children.

[snip requirements]

Please follow the link at the end of this post and read the
document located there. You seem to be under the false
impression that we're here to do your job for you, with no
compensation whatsoever. Can't say about other posters, but
I'm most certainly not.
<xsl:for-each select="TopLevelComponent">

Don't use xsl:for-each unless you understand what it is and
how it works.
<xsl:for-each select="document($archive)">

Gr-r-reat idea.
<xsl:copy-of select="cid($cid)/*"/>

Excellent indentation. Looks great when wrapped to 78
characters. if you don't want help, why don't you just say
so?

Oh, and there's no cid() function in XPath.

<http://www.catb.org/~esr/faqs/smart-questions.html>

NB: You're this >< short of being *plonk*ed.

Wooooow, cool down Pavel! I don't want you to do my job - I just need
help doing it myself!

Okay, maybe I didn't get the hint with the SSCCE but that should not
give you a reason to ... Forget it.
I just don't understand why helped me in such a great way before and
now you talk to me like I'm a stupid kid not knowing that it is
dangerous to walk across the street while the signal's red! But I will
learn from this and I will try make my questioning better. But I must
admit that I feel a little patronized right now. Wasn't I thankful
enough or what is the problem? I just didn't post my complete XML
files before, because I feared being accused of letting you do my job!
And it just happend anyway... :(
I didn't mean it bad. Of course not!

So, okay. I just beg your pardon and try to get back to the topic.
Here are my files (as you would call it SSCCEE):

----- archive.xml -----
<?xml version="1.0" encoding="UTF-8"?>
<PMBv2>
<ARCHIVE>
<Common path="D:/common/common_1.tmp" name="common_1"/>
<Common path="D:/common/common_2.tmp" name="common_2"/>
<Common path="D:/common/common_3.tmp" name="common_3"/>
<Glue path="D:/glue/glue_1.tmp" name="glue_1"/>
<Glue path="D:/glue/glue_2.tmp" name="glue_2"/>
<Mtds path="D:/mtds/mtds_1.tmp" name="mtds_1"/>
<Mtds path="D:/mtds/mtds_2.tmp" name="mtds_2"/>
<Mtds path="D:/mtds/mtds_3.tmp" name="mtds_3"/>
<Mtds path="D:/mtds/mtds_4.tmp" name="mtds_4"/>
<Mtds path="D:/mtds/mtds_5.tmp" name="mtds_5"/>
<Mtds path="D:/mtds/mtds_6.tmp" name="mtds_6"/>
<Mtds path="D:/mtds/mtds_7.tmp" name="mtds_7"/>
<Mtds path="D:/mtds/mtds_8.tmp" name="mtds_8"/>
<Mtds path="D:/mtds/mtds_9.tmp" name="mtds_9"/>
<Module path="D:/module-specific/module_mt_m1235_3_{MNCL}{MNCN}
{MNMI}.tmp" mid="m1235" moduleName="MODULE-MT-M1235-3-TMP" variant="3"
tokens="{MNCL}{MNCN}{MNMI}" tc="D:/module_tc/module_mt_m1235_tc.tmp"/>
<Module path="D:/module-specific/module_mt_m1237_2_subsystemA_{MNCL}
{MNCN}{MNMI}.tmp" mid="m1237" moduleName="MODULE-MT-M1237-2-SUBSYSTEMA-
TMP" variant="2" subsystem="subsystemA" tokens="{MNCL}{MNCN}{MNMI}"
tc="D:/module_tc/module_mt_m1237_tc.tmp"/>
<Product path="D:/product-specifc/product_mt_product_9000_{MNCL}
{MNCN}{MNMI}.tmp" cid="5500" moduleName="PRODUCT-MT-PRODUCT-9000-MIB"
tokens="{MNCL}{MNCN}{MNMI}"/>
<Product path="D:/product-specifc/
product_mt_product_5500_subsystemX_{MNCL}{MNCN}{MNMI}.tmp" cid="5500"
moduleName="PRODUCT-MT-PRODUCT-5500-SUBSYSTEMX-MIB"
subsystem="subsystemX" tokens="{MNCL}{MNCN}{MNMI}" tc="D:/module_tc/
product_mt_product_5500_tc.tmp"/>
</ARCHIVE>
</PMBv2>


----- prodtree.xml -----
<?xml version="1.0" encoding="UTF-8"?>
<PMBv2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="D:\PMBv2\install
\pmbv2_prodtree_schema.xsd">
<PRODUCT_TREE productName="MyProduct" description="Text"
softwareVersion="2.0">
<TopLevelComponent topLevelModule="M14" cid="1700"
description="Text">
<Module selectedModule="MODULE-MT-M1235-3-MIB" instance="23"
description="Text"/>
<Component topLevelModule="M16" cid="1300" description="Component
description.">
<Module instance="12" description="Text" selectedModule="MODULE-MT-
M1236-2-TMP"/>
<SubComponent topLevelModule="M16" cid="5500" description="Text">
<Module instance="10" description="Text" selectedModule="MODULE-
MT-M1235-3-TMP"/>
</SubComponent>
<SubComponent topLevelModule="M14" cid="1300" description="Text">
<Module instance="17" description="Text" selectedModule="MODULE-
MT-M1235-4-TMP"/>
<SubComponent topLevelModule="M9" cid="9000" description="Text">
<Module instance="12" description="Text" selectedModule="MODULE-
MT-M1235-3-TMP"/>
</SubComponent>
</SubComponent>
</Component>
</TopLevelComponent>
</PRODUCT_TREE>
</PMBv2>

So, what I want to do now - ME, not you! But of course I need your
help - is the following:
- copy all <Common>, <Glue> and <Mtds> nodes to prodtree.xml

For each node in prodtree.xml check if
- there is a <Product> in archive.xml with the same cid attribute.
-->if so: append all attributes (that would then be: path, subsystem,
moduleName and tokens) to my <*Component> node in prodtree.xml
- there is a <Module> in archive.xml where the moduleName attribute
has the same value as my current selectedModule attribute
--> if so: append all attributes (that would then be: path, mid,
variant, tokens, tc and subsystem) to the my <Module> node in
prodtree.xml

BTW: I know that the code I posted before made no sense - but believe
it or not, thats a copy&paste from a small tutorial I found while
googleing... So I just gave it a shot! Thats how I learn... Trial and
error until I get it working. Stop *plonk*ing me for that. :p

Another BTW: I already signed up for a XSLT workshop in January. I
just mentioned that to avoid further charges.
 
P

Pavel Lepin

Christian Rühl said:
[snip requirements]

Please follow the link at the end of this post and read
the document located there. You seem to be under the
false impression that we're here to do your job for you,
with no compensation whatsoever. Can't say about other
posters, but I'm most certainly not.

[...]

<http://www.catb.org/~esr/faqs/smart-questions.html>

NB: You're this >< short of being *plonk*ed.

Wooooow, cool down Pavel! I don't want you to do my job -
I just need help doing it myself!

But you don't seem to be interested in making it easier for
others to help you. Oh well, it's your life.
I just don't understand why helped me in such a great way
before and now you talk to me like I'm a stupid kid not
knowing that it is dangerous to walk across the street
while the signal's red!

Umm... because you walked across the street while the
light's red? Makes sense now, doesn't it?
Wasn't I thankful enough or what is the problem?

It's not about being thankful. You didn't follow the URL I
posted, did you?
So, okay. I just beg your pardon and try to get back to
the topic. Here are my files (as you would call it
SSCCEE):

[snip]

*sigh* Did you even read what I wrote in the message you
responded to? I'll repeat:

Is all of the stuff you posted relevant to your question? In
no way. You want to copy some nodes from a different
document. The business case behind that is largely
irrelevant for your predicament.

[snip detailed requirements]

I'll try putting it this way: why do you simply reproduce
the requirements for your software? Why can't you put it
into the terms of something along the lines of: "I have a
number of XML documents, one them being my primary
document, and I need to produce an expanded it by appending
some data from my secondary documents", and illustrate it
with something like:

<primary>
<module id="1"/>
<module id="2"/>
<module id="3"/>
</primary>

<secondary>
<module id="2" foo="yes" bar="no"/>
</secondary>

*This* is an SSCCE for your problem.

To actually solve this problem, you need to know a few
things:

1. How to write basic XPath1 expressions (using axes and
predicates).
2. How to write XPath1 expressions using document()
function.
3. How to define XSLT1 templates for generating result
trees for certain nodes.
4. How to invoke template application on a nodeset produced
by an XPath1 expression in XSLT1.

All of these skills can be obtained by having XPath and XSLT
references next to your cup of coffee, skimming XSLT FAQ to
see if there are any examples that are relatively easy to
understand, then using the Intelligent Try, Err, Grok
approach to see if you've really figured it out.
BTW: I know that the code I posted before made no sense -
but believe it or not, thats a copy&paste from a small
tutorial I found while googleing... So I just gave it a
shot! Thats how I learn... Trial and error until I get it
working.

Despite many claims to the contrary, this approach Just Does
Not Work, which your postings just happen to illustrate.
You should work towards understanding, not just hack
randomly until something gives. Sorry if that sounds
patronising, feel free to ignore this bit of advice.
Another BTW: I already signed up for a XSLT workshop in
January. I just mentioned that to avoid further charges.

So perhaps you should put this task on hold until after
you've finished with that workshop? Alternatively, you
could dive into it and acquire a working knowledge of
XPath1 and XSLT1 over the course of a week or so.
Stop *plonk*ing me for that. :p

Sorry, I don't think this leads anywhere. Perhaps one of the
group regulars would be willing to help you. I'm not
anymore.
 
C

Christian Rühl

What the hell makes you react like I just came through your door and
started dissing you? I didn't make any harm, did I? You wanted a valid
source file... Well, it is valid! And I don't give out any business
secrets by posting it. Maybe I just can't express myself in English,
but... I wish I could understand your reaction. We "know" each other
since three or four posts and all of a sudden you patronize me. I
wouldn't do that with a noob that politely asked a question!

I guess I won't get help here any longer thanks to this lame fight...

I surely understand your hints, but if you once checked out my profile
you'd see that I don't have too much experience to make it right for
everybody in a Usenet newsgroup! I just don't know it better and your
reaction makes me guess that this is more relevant to you than the
fact that I am willing to learn! It not that I ignore your words only
waiting for the solution of my problem... Aw, whatever!
 
J

Joe Kesselman

Christian said:
- for all <*Component> nodes: check if there is a <Product> node in
archive.xml with the same cid? if so: copy all other attributes from
that node.
- for all <Module> nodes: check if there is a <Module> node in
archive.xml with the selectedModule == moduleName? if so: copy all
other attributes from that node.

Start with the identity transform (see the XSLT spec or any decent XSLT
tutorial). That gives you a framework which passes most of the document
through unchanged. Now add templates to it to handle the exceptions:

Write a template that matches Module elements, which searches for the
attributes of the matching node in the archive.xml document, and copies
those attributes onto the node before recursing into the Module's children.

Write a template which matches TopLevelComponent and Component elements,
and applies the same basic logic.

Done.
 
C

Christian Rühl

Start with the identity transform (see the XSLT spec or any decent XSLT
tutorial). That gives you a framework which passes most of the document
through unchanged. Now add templates to it to handle the exceptions:

You mean something like that?

<xsl:param name="tree"/>
Write a template that matches Module elements, which searches for the
attributes of the matching node in the archive.xml document, and copies
those attributes onto the node before recursing into the Module's children..

First problem here:
Write a template which matches TopLevelComponent and Component elements,
and applies the same basic logic.

Done.

This is what i did so far:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:eek:utput method="xml" indent="yes"/>
<xsl:param name="archive"/>
<xsl:param name="tree"/>
<xsl:variable name="archiveModules" select="document($archive)//
Module/@mid"/>
<xsl:variable name="archiveProducts" select="document($archive)//
Product/@cid"/>
<xsl:template match="/">
<TOP>
<ARCHIVE>
<xsl:for-each select="document($archive)//Common">
<Common name="{@name}" path="{@path}"/>
</xsl:for-each>
<xsl:for-each select="document($archive)//Glue">
<Glue name="{@name}" path="{@path}"/>
</xsl:for-each>
<xsl:for-each select="document($archive)//Mtds">
<Mtds name="{@name}" path="{@path}"/>
</xsl:for-each>
</ARCHIVE>
<!-- <xsl:copy-of select="document($tree)/*/*"/> -->
</PRODUCT_TREE>
</TOP>
</xsl:template>
</xsl:stylesheet>

The <ARCHIVE> section works fine, that wasn't that hard to get - even
though I have to admit that i spend some time finding it out. :)

But what definitely doesn't work yet is that part: <xsl:copy-of
select="document($tree)//*[@cid = $archiveProducts]"/>

How can I compare the "identifying attribute" of the actual node to
the corresponding nodes/attributes ofthe secondary document?

Thanks a lot for not letting me down! I appreciate that!
 
J

Joe Kesselman

Christian said:
You mean something like that?

<xsl:param name="tree"/>
<xsl:copy-of select="document($tree)/*/*"/>

No, I mean what I said: Look up "identity transformation" in the spec
(http://www.w3.org/TR/xslt#copying) or in any decent XSLT tutorial
(which should have either exactly this template or an equivalent
thereof). Then write additional templates to recognize the exceptions to
the identity transformation's copy-input-to-output behavior and process
them appropriately.
This is what i did so far:

I saw it. I'm suggesting you discard it and try again from scratch using
the identity-with-exceptions approach I suggested.

At least, assuming your description of what you wanted to achieve is
correct.
How can I compare the "identifying attribute" of the actual node to
the corresponding nodes/attributes ofthe secondary document?

Retrieve the value from the "actual node", and write an XPath expression
which selects the corresponding nodes, using a predicate in the XPath do
to express the fact that the values much match. Let XPath do the work of
finding it for you.
 
C

Christian Rühl

No, I mean what I said: Look up "identity transformation" in the spec
(http://www.w3.org/TR/xslt#copying) or in any decent XSLT tutorial
(which should have either exactly this template or an equivalent
thereof).

Okay, that's what I did. If I understand this correctly: this just
copies it all to the memory, right?
But my version is not working. I have both source files given to the
XSLT script a parameters:

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

To copy&paste the version shown in the spec just can't work, right? I
mean, there's no chance to copy any node with that: match="@*|node()".

If I understand you correctly:
- you want me to make a clean copy of it all (both documents on their
own, of course?)
- then, concerning on those "template"-functions I should build my
selection procedure using XPath

Puh, that'll be a hard challenge... And I still don't have a foot in
the door. Slowly a feeling arises that using XSLT is a little too
overpowered for my project... This is just a wall I'm trying to run
through here.
 
C

Christian Rühl

OK, break. I guess I'm getting closer now...

There's still one problem: By now I just get the top-level-nodes
attributes by using something like this: <xsl:value-of
select="$archiveDoc//Product/@moduleName"/>
How do I get the right nodes attribute here? I have to retrieve the
right node's attribute depending on the cid-attribute. But how do I
put that into the pattern "$archiveDoc//Product/@moduleName"? Or si
there another way doing this? Maybe with a <xsl:when> part or
something like that?

Here's my entry-template (the other ones look similar):

<xsl:template name="component" match="/">
<xsl:for-each select="$treeDoc//Component">
<Component topLevelModule="{@topLevelModule}"
description="{@description}" cid="{@cid}">
<xsl:if test="@cid = $archiveDoc//Product/@cid">
<xsl:attribute name="moduleName"><xsl:value-of
select="$archiveDoc//Product/@moduleName"/></xsl:attribute>
<xsl:attribute name="subsystem"><xsl:value-of
select="$archiveDoc//Product/@subsystem"/></xsl:attribute>
<xsl:attribute name="tokens"><xsl:value-of select="$archiveDoc//
Product/@tokens"/></xsl:attribute>
<xsl:attribute name="path"><xsl:value-of select="$archiveDoc//
Product/@path"/></xsl:attribute>
<xsl:attribute name="tc"><xsl:value-of select="$archiveDoc//
Product/@tc"/></xsl:attribute>
</xsl:if>
<xsl:if test="SubComponent">
<xsl:call-template name="sub-component"/>
</xsl:if>
</Component>
</xsl:for-each>
</xsl:template>
 
C

Christian Rühl

OK, break. I guess I'm getting closer now...

There's still one problem: By now I just get the top-level-nodes
attributes by using something like this: <xsl:value-of
select="$archiveDoc//Product/@moduleName"/>
How do I get the right nodes attribute here? I have to retrieve the
right node's attribute depending on the cid-attribute. But how do I
put that into the pattern "$archiveDoc//Product/@moduleName"? Or si
there another way doing this? Maybe with a <xsl:when> part or
something like that?

Here's my entry-template (the other ones look similar):

<xsl:template name="component" match="/">
<xsl:for-each select="$treeDoc//Component">
<Component topLevelModule="{@topLevelModule}"
description="{@description}" cid="{@cid}">
<xsl:if test="@cid = $archiveDoc//Product/@cid">
<xsl:attribute name="moduleName"><xsl:value-of
select="$archiveDoc//Product/@moduleName"/></xsl:attribute>
<xsl:attribute name="subsystem"><xsl:value-of
select="$archiveDoc//Product/@subsystem"/></xsl:attribute>
<xsl:attribute name="tokens"><xsl:value-of select="$archiveDoc//
Product/@tokens"/></xsl:attribute>
<xsl:attribute name="path"><xsl:value-of select="$archiveDoc//
Product/@path"/></xsl:attribute>
<xsl:attribute name="tc"><xsl:value-of select="$archiveDoc//
Product/@tc"/></xsl:attribute>
</xsl:if>
<xsl:if test="SubComponent">
<xsl:call-template name="sub-component"/>
</xsl:if>
</Component>
</xsl:for-each>
</xsl:template>

Solution found: <xsl:attribute name="moduleName"><xsl:value-of
select="$archiveDoc//Product[attribute::cid=$compID]/@moduleName"/></
xsl:attribute>

Thank you and sorry for taxing your patience.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top