Hi

I recently developed a reportingApp which after downloading xml report from third party, converts it into csv format.

This 3 party changed the dtd version of the reports saying it should not affect anyone

But my app broke as the xmlns reference changed, thus it didn't performed conversion.

so the xml report looks like as follow: (version 1_7)

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Report SYSTEM "https://abc.xxx.com/abc/reports/dtd/report_1_7.dtd">
<Report Name="Detail Report"
Version="1.7"
xmlns="https://abc.xxx.com/abc/reports/dtd/report_1_7.dtd"
ReportStartDate="2009-09-03T07:00:00-07:00"
ReportEndDate="2009-09-04T07:00:00-07:00">
........


and my xslt file is: (version 1_6)

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ebc=<A href="https://abc.xxx.com/abc/reports/dtd/report_1_6.dtd">https://abc.xxx.com/abc/reports/dtd/report_1_6.dtd</A>>
<xsl:strip-space elements="*"/>
<xsl:param name="lb" select="''"/>
<xsl:param name="sep" select="','"/>
........

How can I tackle this kind of problem ?

Thanks in advance

Hi

Thanks for the reply.
I am posting the xslt code in Code box.

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ebc="https://abc.xxx.com/abc/reports/dtd/report_1_6.dtd">
<xsl:strip-space elements="*"/>
<xsl:param name="lb" select="''"/>
<xsl:param name="sep" select="','"/>
<xsl:template match="ebc:Request">
     <xsl:value-of select="concat($lb,/ebc:Report/@MID, $sep, @RefNo,$sep, ebc:PMethod/ebc:Cno/ebc:Type,
$sep, ebc:PMethod/ebc:Code, $sep, ebc:Bill/ebc:CustomerID, $sep, @RequestDate, $sep)"/>
....
....

You've got yourself an interesting problem. this has nothing to do with the DTD directly, but the namespaces. They are declaring a default namespace that has changed. Not only is this bad design, but ti creates all kinds of problems for XSLT writers like yourself :) Especially in 1.0

Your transformation creates a temporary namespace, with a prefix, that is the same as the default namespace in the input document. This allows you to match on the input document nodes of the default namespace. If they keep changing this, your code will break everytime they change. You could simple change your prefixed namespace declaration everytime they change to whatever the default is.

Like

xmlns:ebc="https://abc.xxx.com/abc/reports/dtd/report_1_7.dtd"

The other option you have is to write a transformation that doesn't CARE what namespace the input nodes are in. This is done by changing every every "match", "select" or any other instruction to a namespace agnostic form.

So instead of having.

<xsl:template match="ebc:Report" />

You would write.

<xsl:template match="*[local-name() = 'Report']" />

This means it matches any input node, whose local-name() is Report. This would solve your problem and them it wouldn't matter what namespace your input document is in.

The other options is to use Java or C# to dynamically built your transformation with the correct namespace before it's executed.

Hi
Thanks a lot !
Previously, I had opted for the first solution, simply changing the namespace.
But reading your solutions, I have tried with the second one and it has worked.
But what will you suggest, option 2 or option 3 ?
Are there any drawbacks for option 2 ?

The best option that makes your code the most flexible is to make it namespace agnostic (*[local-name() = 'Report']), so it doesn't matter what namespace the input document is in. This takes the most work.

But the real problem in this case is the design of their input document. You should almost never have a namespace that's based off a file name that changes like that.

Thanks a lot for you suggestions

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.