Reputation: 192
im stuck at this point:
XML source
<config>
<username>user</username>
<password>pass</password>
<link>1.2.3.4</link>
<port>99</port>
</config>
XML target
<some wrapping="tag"> <!-- is fixed and should be just inserted -->
<property name="username" value="user"/>
<property name="password" value="pass"/>
<!-- link and port are merged into one attribute -->
<property name="URL" value="1.2.3.4:99" />
</some>
XSLT i have so far
<xsl:template match="config">
<some wrapping="tag">
<xsl:apply-templates />
</some>
<xsl:template>
<xsl:template match="config/username | config/password">
<property name="{local-name()}">
<xsl:attribute name="value">
<xsl:value-of select="." />
</xsl:attribute>
</property>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
It gives me desired result until it comes to the point of merging link and port nodes into URL property with value of port and link.
Thanks in advance!
Upvotes: 2
Views: 116
Reputation: 243449
Even shorter:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*" priority="10">
<some wrapping="tag">
<xsl:apply-templates/>
</some>
</xsl:template>
<xsl:template match="*[not(self::port)]">
<property name="{concat(substring(name(), string-length(name())*(name()='link') +1),
substring('URL', 3*(not(name()='link')) +1))}"
value="{concat(.,substring(concat(':',../port),
(string-length(../port)+1)*not(name()='link')+1) )}"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
Do note:
The <property>
element is constructed only in a single place in the code, regardless of the name of the element that is matched by the template.
The code is generic and doesn't mention explicitly element names such as "username
" or "password
"
Upvotes: 1
Reputation: 6061
If you want a transparent and easy to read solution, just code:
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="config">
<some wrapping="tag">
<property name="username" value="{username}"/>
<property name="password" value="{password}"/>
<!-- link and port are merged into one attribute -->
<property name="URL" value="{link}:{port}" />
</some>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Reputation: 116992
How about:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/config">
<some wrapping="tag">
<xsl:apply-templates select="username | password"/>
<property name="URL" value="{concat(link, ':', port)}" />
</some>
</xsl:template>
<xsl:template match="*">
<property name="{local-name()}">
<xsl:attribute name="value">
<xsl:value-of select="." />
</xsl:attribute>
</property>
</xsl:template>
</xsl:stylesheet>
Or just:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/config">
<some wrapping="tag">
<xsl:for-each select="username | password">
<property name="{local-name()}">
<xsl:attribute name="value">
<xsl:value-of select="." />
</xsl:attribute>
</property>
</xsl:for-each>
<property name="URL" value="{concat(link, ':', port)}" />
</some>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2