[xsl] Implementing unparsed-entity-uri() in MS script

Subject: [xsl] Implementing unparsed-entity-uri() in MS script
From: Dan Vint <dvint@xxxxxxxxx>
Date: Mon, 16 Apr 2012 20:37:57 -0700
I have an application (3rd party) that uses MS .net and the MS XSL parser. My XML uses entity definitions to store the path to a graphic. So the XML looks something like this:

<!DOCTYPE dmodule [
<!ENTITY ICN-S1000DBIKE-AAA-D000000-0-U8025-00536-A-04-1 SYSTEM "ICN-S1000DBIKE-AAA-D000000-0-U8025-00536-A-04-1.CGM" NDATA cgm>
]>
<dmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
xsi:noNamespaceSchemaLocation="http://www.s1000d.org/S1000D_3-0/xml_schema_flat/descript.xsd"";>


<figure>
<figure id="fig-0001">
<title>Complete bicycle</title>
<graphic boardno="ICN-S1000DBIKE-AAA-D000000-0-U8025-00536-A-04-1"/>
</figure>

</dmodule>

With a straight XSLT approach I would use unparsed-entity-uri() to get the actual file name and path when I process the graphic tag. But this is not implemented in MSXSLT.

The following code is a good approximation of this function, but it only retrieves the entity definition:

<ms:script implements-prefix="user" xmlns:ms="urn:schemas-Microsoft-com:xslt" language="C#">
<![CDATA[
public string getEntityURI(XPathNodeIterator node, string entityName) {
if (node.MoveNext()) {
XmlDocument document = ((IHasXmlNode)node.Current).GetNode().OwnerDocument;
XmlEntity entity = (XmlEntity)document.DocumentType.Entities.GetNamedItem(entityName);
return entity.SystemId;
}
return "";
}
]]>
</ms:script>


The 3rd party application uses an additional plug in to display the graphic. That application requires the full system path to the file - I can't use a relative path. The graphic is in the same directory as the XML document.

So I'm looking for some way to get the base URI for the document and then append that to the graphic entity. I'm not a MS programmer and I'm hoping someone can help out. I've tried this change:


<ms:script implements-prefix="user" xmlns:ms="urn:schemas-microsoft-com:xslt" language="C#">
<ms:assembly name="System" />
<ms:assembly name="System.IO" />
<ms:using namespace="System.IO" />
<![CDATA[
public string getEntityURI(XPathNodeIterator node, string entityName) {
if (node.MoveNext()) {
string root = Path.GetPathRoot(node.Current.attributes[0].baseURI);
XmlDocument document = ((IHasXmlNode)node.Current).GetNode().OwnerDocument;
XmlEntity entity = (XmlEntity)document.DocumentType.Entities.GetNamedItem(entityName);
return root + "\\" + entity.SystemId;
}
return "";
}
]]>
</ms:script>


But the application kicks back with:

"Metadata file 'System.IO.dll' could not be found

at System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver) at ADG_SGML_Converter.SGML_Conv.GetTransformResult(String sXSL) "

First question is should my script code do what I expect? I haven't figured out anyway to test this separate from the 3rd party application.

Second, now that I look at the message it looks like the error is with the 3rd party application call.

I've been trying to run the stylesheet standalone with Stylus Studio but there I get an error about finding a function in the namespace:

"Cannot find a matching 2 argument function named ...getEntityURI()"

If I hard code the path into the function then the 3rd party application works. So that portion appears to be ok within the application and not StylusStudio. Here is the template that calls this function

<xsl:template match="graphic" mode="singlesheet">
<div class="image">
<object height="400" width="600" type="application/x-isoview" classid="CLSID:865B2280-2B71-11D1-BC01-006097AC382A"
id="ivx1" imageType="graphic">
<param value="1" name="border"/>
<param name="src" value="{user:getEntityURI(., @boardno)}"/>
<!-- <param name="src" value="C:\Documents and Settings\dvint\Desktop\IETP bike 3.0\Files\ICN-S1000DBIKE-AAA-D000000-0-U8025-00536-A-04-1.CGM"/> -->
</object>
<script language="javascript">
function configEvent() {
document.ivx1.ConfigEvents(1+2+4+8+16+32+1024);
}
</script>
<script language="javascript" for="ivx1"
event="HsHit(nMouseBtn, lRefID, strName, strViewPortName, strViewPortFile)">
myHsHit(nMouseBtn, lRefID, strName, strViewPortName, strViewPortFile);
</script>
</div>


<p><b><a href="R4I_CANCEL">
<xsl:attribute name="onclick">window.external.ShowImage('<xsl:value-of select="string(@boardno)"/>', <xsl:value-of select="count(preceding::figure)+1"/>)</xsl:attribute>
Figure <xsl:value-of select="count(preceding::figure)+1"/>&em;<xsl:value-of select="../title"/></a></b></p>
</xsl:template>


Any ideas or pointers appreciated.

thanks

..dan
---------------------------------------------------------------------------
Danny Vint

Panoramic Photography
http://www.dvint.com

voice: 619-938-3610

Current Thread