Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Change XML format 1

Status
Not open for further replies.

bartvg

Programmer
Jul 27, 2006
5
NL
I have a question about changing the format of an XML file. I know I have to do this with an XSLT, but i can't get it right. How would my XSLT file look like to get te transform as shown below? Regards

Bart



The XML I start with is:

-----------------
<?xml version="1.0" encoding="utf-8" ?>
<dataset xmlns=" xmlns:xs="- <!--
<dataset
xmlns=" xmlns:xs=" xs:schemaLocation=" xmldata.xsd"
>
-->
<metadata>
<item name="Record type" type="xs:string" length="4" />
<item name="Recordcounter" type="xs:int" />
</metadata>
<data>
<row>
<value>U</value>
<value>1</value>
</row>
<row>
<value>U</value>
<value>2</value>
</row>
<row>
<value>U</value>
<value>3</value>
</row>
</data>
</dataset>
-------------------------


The XML I need is:


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

<?xml version="1.0" encoding="utf-8"?>
<dataset xmlns=" xmlns:xs="<!--
<dataset
xmlns=" xmlns:xs=" xs:schemaLocation=" xmldata.xsd"
>
-->
<data>
<row>
<Recordtype>U</Recordtype>
<Recordcounter>1</Recordcounter>
</row>
<row>
<Recordtype>U</Recordtype>
<Recordcounter>2</Recordcounter>
</row>
<row>
<Recordtype>U</Recordtype>
<Recordcounter>3</Recordcounter>
</row>
</data>
</dataset>
----------------------------
 
Like this.
[tt]
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl=" xmlns="<xsl:eek:utput method="xml" indent="yes" encoding="utf-8" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="node()|comment()|@*|processing-instruction()|text()">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="node()[local-name()='metadata']" />
<xsl:template match="node()[local-name()='value']">
<xsl:choose>
<xsl:when test="position()=1">
<Recordtype>
<xsl:value-of select="text()" />
</Recordtype>
</xsl:when>
<xsl:when test="position()=last()">
<Recordcounter>
<xsl:value-of select="text()" />
</Recordcounter>
</xsl:when>
<xsl:eek:therwise>
<!-- nothing -->
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
[/tt]
 
Hi tsuji thanks for your help. I'm not familiar with xml so I have 2 other questions regarding this issue.

1) I want to use this XLST file also to change the fomat of other xml files. The syntax of these xml files are almost the same, the only difference is the following:

------------
<metadata>
<item name="Record type" type="xs:string" length="4" />
<item name="Recordcounter" type="xs:int" />
<item name="Record subtype" type="xs:string" length="4" />
<item name="Recordcounter" type="xs:int" />
<item name="User number" type="xs:int" />
</metadata>
<data>
<row>
<value>U</value>
<value>1</value>
<value>A</value>
<value>1</value>
</row>
--------------

Is it posible to generate also an new xml file of this one with the same XLST stylesheet? (If I place extra statements in the XLST)


My second question is how does the XLST stylesheet transforms the XLM. I generate the origin XML with Cognos ReportNet. The XML is placed on the harddisk. How does The XLST stylesheet transforms the generated XML? Do you have to make some kind of a schedule to do this? I have been looking at stylus studio. Can you do this with that program?

Regards

Bart

 
[1] The simplest is to get some commandline tool. Easiest is microsoft msxsl.exe utility (free downloadable). With it, you can make the transformation with the line like this.
[tt]
msxsl source.xml sourse.xsl -o result.xml -xw
[/tt]
There are abundance of such utilities, too much distraction than you can concentrate on the central task to get familiar with. I just happen to use more often the simplest and most handy for xslt1.0 support. Beyond that, also plenty...

[2] In your new <row>, it sure can do using position() to determine what to do with each in the sequence. But, you have not specified what to target... like <Recordtype>, <Recordcount>,... for each.
 
What if the source XML has a different name every time. Is it posible to use the msxsl.exe utility?
 
Same... they are just symbolic names. They can include exact path to make they unambiguous.
 
Hi tsuji


One more question regarding the XSLT stylesheet. How would the sylesheet look like for this xml input. I still want to use the same stylesheet for the first xml?

Thanks,

Bart

------------
<metadata>
<item name="Record type" type="xs:string" length="4" />
<item name="Recordcounter" type="xs:int" />
<item name="Record subtype" type="xs:string" length="4" />
<item name="User number" type="xs:int" />
<item name="Quantity" type="xs:int" />
</metadata>
<data>
<row>
<value>U</value>
<value>1</value>
<value>A</value>
<value>1</value>
<value>50</value>
</row>
 
I have asked for clarification already in my previous post (paragraph [2]).
 
By guessing what you want, try this.
[tt]
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl=" xmlns="<xsl:eek:utput method="xml" indent="yes" encoding="utf-8" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="node()|comment()|@*|processing-instruction()|text()">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="node()[local-name()='metadata']" />
<xsl:template match="node()[local-name()='value']">
<xsl:if test="position() mod 2 = 0">
<Recordtype>
<xsl:value-of select="text()" />
</Recordtype>
</xsl:if>
<xsl:if test="position() mod 2 = 1">
<Recordcounter>
<xsl:value-of select="text()" />
</Recordcounter>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
[/tt]
 
Hi Tsuji,

Sorry for the misunderstanding.

What I need is an XSLT stylesheet that can handle different xml input.

The first input could be:

----
<metadata>
<item name="Record type" type="xs:string" length="4" />
<item name="Recordcounter" type="xs:int" />
<item name="Record subtype" type="xs:string" length="4" />
<item name="User number" type="xs:int" />
<item name="Quantity" type="xs:int" />
</metadata>
<data>
<row>
<value>U</value>
<value>1</value>
<value>A</value>
<value>1</value>
<value>50</value>
</row>

-----

The secound input could be:

---
<metadata>
<item name="Record type" type="xs:string" length="4" />
<item name="Recordcounter" type="xs:int" />
<item name="Plantnumber" type="xs:int" />
<item name="Description" type="xs:string" length="4" />
<item name="Date" type="xs:string" length="4" />
<item name="Quantity" type="xs:int" />
</metadata>
<data>
<row>
<value>U</value>
<value>1</value>
<value>10</value>
<value>Main plant</value>
<value>310706</value>
<value>50</value>
</row>
--

Now there the 'value' is replaced by the sequence of the items. Is this possible?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top