XSLT problem
Here should go questions about transforming XML with XSLT and FOP.
-
- Posts: 4
- Joined: Thu Aug 10, 2006 1:44 pm
- Contact:
XSLT problem
Hello,
I have this input file that I want to transform:
I have this additional xml file:
The goal of the XSLT is to insert virtual-node element with attribute name and value of this attribute equal of the corresponding execution context, in the component elements. The result after my XSLT transformation is:
That is what i managed to do with the folowing XSL :
But the problem is that there is difference between the component inMore in more and the component inMore in server. So I want to reference the components in the deployment xml file like this :
<component-name>server/inMore</component-name>
<component-name>more/inMore</component-name>
<component-name>more/inMore/inInMore-2</component-name>
The problem is that I dont know how to modify the XSLT to do now the insertion of virtual-node-s correctly.
Do you have any suggestions?
One particular problem that I have is that I dont know how to reference for example ONLY the second child component of the root element. "child::component[position()=2]" returns to me not only the component "more" but also the second component in it "inMore-second".
Violeta
I have this input file that I want to transform:
Code: Select all
<definition name="fr.inria.test.clientServerComp" extends="fr.inria.test.rootType">
<component name="client" definition="fr.inria.test.client" />
<component name="more" definition="fr.inria.test.more" >
<component name="inMore">
<interface name="blabla" signature="olala"></interface>
<component name="inInMore-1">
<interface name="blabla" signature="olala"></interface>
</component>
<component name="inInMore-2">
<interface name="blabla" signature="olala"></interface>
</component>
</component>
<component name="inMore-second">
<interface name="blabla" signature="olala"></interface>
</component>
</component>
<component name="server" definition="fr.inria.test.server" />
<component name="inMore" definition="fr.inria.test.more"/>
</component>
<binding client="this.runnableItf" server="client.runnableItf" />
<binding client="client.print" server="server.print" />
</definition>
I have this additional xml file:
Code: Select all
<fractal-deployment>
<real-host name="Belote">
<virtual-host name="VH2" type="jvm">
<execution-context name="EC2" >
<content>
<component-name>server</component-name>
</content>
</execution-context>
</virtual-host>
<ip>138.96.64.61</ip>
</real-host >
<real-host name="Parlote">
<virtual-host name="VH1" type="jvm">
<execution-context name="EC1" >
<content>
<component-name>client</component-name>
<component-name>inMore</component-name>
</content>
</execution-context>
</virtual-host>
</real-host>
</fractal-deployment>
Code: Select all
<definition name="fr.inria.test.clientServerComp" extends="fr.inria.test.rootType">
<component name="client" definition="fr.inria.test.client" >
<virtual-node name="EC1">
</component>
<component name="more" definition="fr.inria.test.more" >
<component name="inMore">
<interface name="blabla" signature="olala"></interface>
<component name="inInMore-1">
<interface name="blabla" signature="olala"></interface>
</component>
<component name="inInMore-2">
<interface name="blabla" signature="olala"></interface>
</component>
<virtual-node name="EC1">
</component>
<component name="inMore-second">
<interface name="blabla" signature="olala"></interface>
</component>
</component>
<component name="server" definition="fr.inria.test.server" />
<component name="inMore" definition="fr.inria.test.more"/>
<virtual-node name="EC2">
</component>
<binding client="this.runnableItf" server="client.runnableItf" />
<binding client="client.print" server="server.print" />
</definition>
That is what i managed to do with the folowing XSL :
Code: Select all
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:variable name="depl_file" select="document('../data/deployfractal.xml')"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//component">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:variable name="comp_name" select="$depl_file//real-host/virtual-host/execution-context/content/component-name/text()"/>
<xsl:if test="current()/@name=$comp_name">
<xsl:element name="virtual-node">
<xsl:attribute name="name">
<xsl:value-of select="$depl_file//real-host/virtual-host/execution-context[content/component-name/text() = current()/@name]/@name"/>
</xsl:attribute>
</xsl:element>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:transform>
But the problem is that there is difference between the component inMore in more and the component inMore in server. So I want to reference the components in the deployment xml file like this :
<component-name>server/inMore</component-name>
<component-name>more/inMore</component-name>
<component-name>more/inMore/inInMore-2</component-name>
The problem is that I dont know how to modify the XSLT to do now the insertion of virtual-node-s correctly.
Do you have any suggestions?
One particular problem that I have is that I dont know how to reference for example ONLY the second child component of the root element. "child::component[position()=2]" returns to me not only the component "more" but also the second component in it "inMore-second".
Violeta
-
- Posts: 4141
- Joined: Fri Mar 28, 2003 2:12 pm
Re: XSLT problem
Post by sorin_ristache »
Hello,
instead of
Please post the expected result file for the 2 given XML files and the XSL file.
Regards,
Sorin
I am not sure what you mean by only the second child component of the root element. A node returned by an XPath expression always includes all the child nodes of that node. That is the "more" component (<component name="more" definition="fr.inria.test.more">) always includes the "inMore-second" component (<component name="inMore-second">).panpilulu wrote:One particular problem that I have is that I dont know how to reference for example ONLY the second child component of the root element. "child::component[position()=2]" returns to me not only the component "more" but also the second component in it "inMore-second".
The result that I get with your sample files has a couple of differences. It containspanpilulu wrote:I have this input file that I want to transform:
...
I have this additional xml file:
...
The result after my XSLT transformation is:
...
That is what i managed to do with the folowing XSL :
...
Code: Select all
<component name="server" definition="fr.inria.test.server">
<virtual-node name="EC2"/>
</component>
<component name="inMore" definition="fr.inria.test.more">
<virtual-node name="EC1"/>
</component>
Code: Select all
<component name="server" definition="fr.inria.test.server"/>
<component name="inMore" definition="fr.inria.test.more"/>
<virtual-node name="EC2"/>
Also post the final form of the input files including deployfractal.xml.panpilulu wrote:So I want to reference the components in the deployment xml file like this :
<component-name>server/inMore</component-name>
<component-name>more/inMore</component-name>
<component-name>more/inMore/inInMore-2</component-name>
Regards,
Sorin
-
- Posts: 4
- Joined: Thu Aug 10, 2006 1:44 pm
- Contact:
Sorry my first post is not very clear and even contains an error.
Thank you Sorin. I will explain. So we keep the first file.
We modify the second
The expected result
I wold like to modify the xsl file to do this....
Thank you Sorin. I will explain. So we keep the first file.
Code: Select all
<definition name="fr.inria.test.clientServerComp" extends="fr.inria.test.rootType">
<component name="client" definition="fr.inria.test.client" />
<component name="more" definition="fr.inria.test.more" >
<component name="inMore">
<interface name="blabla" signature="olala"></interface>
<component name="inInMore-1">
<interface name="blabla" signature="olala"></interface>
</component>
<component name="inInMore-2">
<interface name="blabla" signature="olala"></interface>
</component>
</component>
<component name="inMore-second">
<interface name="blabla" signature="olala"></interface>
</component>
</component>
<component name="server" definition="fr.inria.test.server" />
<component name="inMore" definition="fr.inria.test.more"/>
</component>
<binding client="this.runnableItf" server="client.runnableItf" />
<binding client="client.print" server="server.print" />
</definition>
Code: Select all
<fractal-deployment>
<real-host name="Belote">
<virtual-host name="VH2" type="jvm">
<execution-context name="EC2" >
<content>
<component-name>server/inMore</component-name>
</content>
</execution-context>
</virtual-host>
<ip>138.96.64.61</ip>
</real-host >
<real-host name="Parlote">
<virtual-host name="VH1" type="jvm">
<execution-context name="EC1" >
<content>
<component-name>client</component-name>
<component-name>more/inMore/inInMore-1</component-name>
</content>
</execution-context>
</virtual-host>
</real-host>
</fractal-deployment>
Code: Select all
<definition name="fr.inria.test.clientServerComp" extends="fr.inria.test.rootType">
<component name="client" definition="fr.inria.test.client" />
<virtual-node name="EC1">
</component>
<component name="more" definition="fr.inria.test.more" >
<component name="inMore">
<interface name="blabla" signature="olala"></interface>
<component name="inInMore-1">
<interface name="blabla" signature="olala"></interface>
<virtual-node name="EC1">
</component>
<component name="inInMore-2">
<interface name="blabla" signature="olala"></interface>
</component>
</component>
<component name="inMore-second">
<interface name="blabla" signature="olala"></interface>
</component>
</component>
<component name="server" definition="fr.inria.test.server" />
<component name="inMore" definition="fr.inria.test.more"/>
<virtual-node name="EC2">
</component>
</component>
<binding client="this.runnableItf" server="client.runnableItf" />
<binding client="client.print" server="server.print" />
</definition>
-
- Posts: 4
- Joined: Thu Aug 10, 2006 1:44 pm
- Contact:
I think I found a way

Thanks to all of you!

Code: Select all
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:variable name="depl_file" select="document('../data/deployfractal.xml')"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//component">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:variable name="comp_name_depl" select="$depl_file//real-host/virtual-host/execution-context/content/component-name/text()"/>
<xsl:variable name="comp_name_fract">
<xsl:if test="current()/parent::component">
<xsl:for-each select="current()/ancestor::component">
<xsl:value-of select="concat(current()/@name,'/')"/>
</xsl:for-each>
</xsl:if>
<xsl:value-of select="current()/@name"/>
</xsl:variable>
<xsl:if test="$comp_name_fract=$comp_name_depl">
<xsl:element name="virtual-node">
<xsl:attribute name="name">
<xsl:value-of select="$depl_file//real-host/virtual-host/execution-context[content/component-name/text() = $comp_name_fract]/@name"/>
</xsl:attribute>
</xsl:element>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:transform>

Thanks to all of you!
-
- Posts: 4141
- Joined: Fri Mar 28, 2003 2:12 pm
Post by sorin_ristache »
Hello Violeta,
You can find below a more compact and simple stylesheet which uses XSLT 2.0. I made the comp_name variable global because it does not depend on the context element of the template so it should be computed only once. You have to apply an XSLT 2.0 processor, for example Saxon 8B.
Regards,
Sorin
You can find below a more compact and simple stylesheet which uses XSLT 2.0. I made the comp_name variable global because it does not depend on the context element of the template so it should be computed only once. You have to apply an XSLT 2.0 processor, for example Saxon 8B.
Code: Select all
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:variable name="depl_file" select="document('../data/deployfractal.xml')"/>
<xsl:variable name="comp_name" select="$depl_file//real-host/virtual-host/execution-context/content/component-name"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="component">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:variable name="complete_name"
select="string-join(for $i in ancestor-or-self::component return $i/@name, '/')"/>
<xsl:if test="$complete_name=$comp_name">
<xsl:variable name="virtual_node_name"
select="for $i in $comp_name return if ($i=$complete_name) then $i/../../@name else ()">
</xsl:variable>
<virtual-node name="{$virtual_node_name}"/>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:transform>
Sorin
Jump to
- Oxygen XML Editor/Author/Developer
- ↳ Feature Request
- ↳ Common Problems
- ↳ DITA (Editing and Publishing DITA Content)
- ↳ SDK-API, Frameworks - Document Types
- ↳ DocBook
- ↳ TEI
- ↳ XHTML
- ↳ Other Issues
- Oxygen XML Web Author
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Content Fusion
- ↳ Feature Request
- ↳ Common Problems
- Oxygen JSON Editor
- ↳ Feature Request
- ↳ Common Problems
- Oxygen PDF Chemistry
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Feedback
- ↳ Feature Request
- ↳ Common Problems
- Oxygen XML WebHelp
- ↳ Feature Request
- ↳ Common Problems
- XML
- ↳ General XML Questions
- ↳ XSLT and FOP
- ↳ XML Schemas
- ↳ XQuery
- NVDL
- ↳ General NVDL Issues
- ↳ oNVDL Related Issues
- XML Services Market
- ↳ Offer a Service