ent3
ent3

Reputation: 192

Merge/concat values of an attribute in xml using xslt

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

Answers (3)

Dimitre Novatchev
Dimitre Novatchev

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:

  1. 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.

  2. The code is generic and doesn't mention explicitly element names such as "username" or "password"

Upvotes: 1

Pierre Fran&#231;ois
Pierre Fran&#231;ois

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

michael.hor257k
michael.hor257k

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

Related Questions