[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1142
  • Last Modified:

xslCompiledTransform undefined entity error on euro symbol

Dear all,

First of all I'm new to XSL transformations and XML processing!

I am dealing with a third party xml file which looks like (fragment):

<?xml version="1.0"?>
<!DOCTYPE mail SYSTEM "http://www.mijnwinkel.nl/DTD/order_v2.dtd"
><mail version="2.0" >
<set id="session" sequence="1" version="1.1" ><property id="calc_vat" label="" sequence="0" resource_label="" show_type="" name="" >1</property>
<property id="emailvendor" label="" sequence="" resource_label="" show_type="" name="" >mvette@avn-ned.com;info@erma-design.nl</property>
<property id="emailvendor_reply" label="" sequence="" resource_label="" show_type="" name="" >mvette@avn-ned.com</property>
<property id="exentedVAT" label="" sequence="0" resource_label="" show_type="" name="" >1</property>
<property id="order_shopnumber" label="" sequence="" resource_label="" show_type="" name="" >2380602</property>
<property id="ordernumber" label="" sequence="" resource_label="" show_type="" name="" >2380600_00020</property>
<property id="shopnumber" label="" sequence="" resource_label="" show_type="" name="" >2380602</property>
<set id="actions" sequence="1" version="" ><property id="active" label="" sequence="0" resource_label="" show_type="" name="" >true</property>
<property id="total" label="" sequence="0" resource_label="" show_type="" name="" >0</property>

The referenced DTD (http://www.mijnwinkel.nl/DTD/order_v2.dtd) look like this:

<!ENTITY nbsp " ">
<!ENTITY euro "&#8364;">
<!ELEMENT set (property | set)*>
<!ATTLIST set sequence CDATA #IMPLIED>
<!ELEMENT property (#PCDATA)>
<!ATTLIST property label CDATA #IMPLIED>
<!ATTLIST property sequence CDATA #IMPLIED>
<!ATTLIST property resource_label CDATA #IMPLIED>
<!ATTLIST property show_type CDATA #IMPLIED>
<!ATTLIST property name CDATA #IMPLIED>
<!ELEMENT mail (set)*>
<!ATTLIST mail version CDATA #IMPLIED>

I have made a xsl script to get some clear xml instead of the recursive 'set' and property elements:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"
    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />
    <xsl:template match="@* | node()">
            <xsl:apply-templates select="@* | node()" />
    <xsl:template match="property">
        <xsl:element name="{@id}" namespace="http://tempuri.org/OrderinfoDataSet.xsd">
            <xsl:apply-templates />
    <xsl:template match="mail">
        <xsl:element name="OrderinfoDataSet" namespace="http://tempuri.org/OrderinfoDataSet.xsd">
            <xsl:apply-templates />
    <xsl:template match="set">
        <xsl:element name="{@id}" namespace="http://tempuri.org/OrderinfoDataSet.xsd">
            <xsl:apply-templates />

Now when applying this in Oxygen xml developer I get (fragment):

<?xml version="1.0" encoding="UTF-8"?>
-<OrderinfoDataSet xmlns="http://tempuri.org/OrderinfoDataSet.xsd">
       <amount-inc-vat>€ 126,35</amount-inc-vat>

With the € coming from "&euro; 126,35"  in the source xml....

Now in C# I'm trying to call this xsl to get a nice converted xml file which I can load against a dataset.
Problem is that the code is going down on the euro-sign:
Reference to undeclared entity 'euro'. Line 13, position 135.

code fragment:

var resolver = new XmlUrlResolver
                            Credentials = System.Net.CredentialCache.DefaultCredentials
                    // xsl template for transformation            
                    var xslCompiledTransform = new XslCompiledTransform();
                    xslCompiledTransform.Load("import.xsl", XsltSettings.Default, resolver);
                    // xml content reader            
                    var settings = new XmlReaderSettings {XmlResolver = null};
                    settings.DtdProcessing = System.Xml.DtdProcessing.Ignore;

                    var xmlSettings = new XmlWriterSettings();
                    //&euro en de lege namespaces in customer

                    var reader = XmlReader.Create(file, settings);
                    using (var w = XmlWriter.Create(temppath + @"\temp.xml", xmlSettings))
                        xslCompiledTransform.Transform(reader, w); //ERROR

My question is:
Can I alter my XSL (entity declarations perhaps) in order to get the transformation done in C# without the error?
Or should I remove all the euro symbols within the code (and how would that look)?

I really don't care about the Euro symbols , as I don't need 'm for further processing.
So if the XSL could be altered in a way that the Euro signs would disappear , that would be fine!

Thank you very much in advance!

Kind regards,
  • 4
1 Solution
Geert BormansCommented:
The XML, DTD and XSLT are all correct.
But you need to makes ure that the DTD is not ignored when running the XSLT.
Without the DTD, the XML is not wellformed due to the Euro entity

I think you need to drop this line and it will be OK
settings.DtdProcessing = System.Xml.DtdProcessing.Ignore;
Geert BormansCommented:
Try this
settings.DtdProcessing = System.Xml.DtdProcessing.Parse;

removing it will set it to the default "Prohibit", but that is not what you want
Geert BormansCommented:
setting the entity declaration on the XSLT would only be usefull if you would want to use th &euro; in the XSLT itself.
Note that the XSLT process wil resolve the entity whilst parsing the XML against the DTD, and from the start of the actual XSLT process up to the transformation result this Euro will be handled as a UTF-8 char
JahwikAuthor Commented:
unfortunately, changing the DtdProcessing property to 'Parse' didn't work. I tried it before.

But, you got me thinking when looking at the previous lines of code:
var settings = new XmlReaderSettings { XmlResolver = null}; (??)

If I change this to:
 var settings = new XmlReaderSettings { XmlResolver = resolver };
(with resolver is of type  XmlUrlResolver , declares earlier), then the transformation goes well.....

So thanks a lot Gertone, I can carry on with the processing ;)

Geert BormansCommented:
sounds good,

Featured Post

NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now