简体   繁体   中英

One to One mapping from One XML to another XML using XSLT

I have two XSDs. The sample XML for these two XSDs are as follows

**XML -1**                            **XML -2**

<root>                                <parent>
  <e1 />                                <a1 />
  <e2 />                                <a2 />
    .                                     .
    .                                     .
    .                                     .
  <e600 />                              <a600/>
</root>                               </parent>

I need to write an XSLT for data transformation. The value of element " e(i) " needs to be mapped to " a(i) "

Now I can write an XSLT like below

<parent>
  <a1>
    <xsl:value-of select = "/root/e1/text()"/>
  </a1>
  <a2>
    <xsl:value-of select = "/root/e2/text()"/>
  </a2>
    .
    .
  <a600>
    <xsl:value-of select = "/root/e600/text()"/>
  </a600>
</parent>

But this way it is very tedious. Anyone can help or suggest whether to write an XSLT for this purpose in a small way within one template using XSLT 1.0.

How about:

XSLT 1.0

<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:strip-space elements="*"/>

<xsl:template match="/root">
    <parent>
        <xsl:apply-templates/>
    </parent>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="a{substring-after(name(), 'e')}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

Added:

In actual XSD, the elements' name are not like this. These 600 elements are having some different names, no number, nothin common

If there is no way to calculate the target element's name from the source, then you must resort to some sort of a lookup . This could be in the form of a template for each element, or xsl:choose or selecting from an array.

For example, you could do:

<xsl:template match="*">
    <xsl:variable name="name">
        <xsl:choose>
            <xsl:when test="name()='e1'">a1</xsl:when>
            <xsl:when test="name()='e2'">a2</xsl:when>
            <xsl:when test="name()='e600'">a600</xsl:when>
        </xsl:choose>
    </xsl:variable>
    <xsl:element name="{$name}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

Or perhaps a bit more efficiently:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://example.com/my"
exclude-result-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="nm" match="name" use="@source" />

<my:name-map>
    <name source="e1">a1</name>
    <name source="e2">a2</name>
    <name source="e600">a600</name>
</my:name-map>

<xsl:template match="/root">
    <parent>
        <xsl:apply-templates/>
    </parent>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="source-name" select="name()" />
    <xsl:variable name="target-name">
        <xsl:for-each select="document('')">
            <xsl:value-of select="key('nm', $source-name)"/>            
        </xsl:for-each>
    </xsl:variable>
    <xsl:element name="{$target-name}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM