Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Hi Friends i need This problem my xml style
<stringtable>
<section>
<string _enum="0x78B5CB94" _extra="0xFFFFFFFF" _id="856571" _value="Anladin.[Timing 0.43 0.00 1]" />
<string _enum="0xA980AB0A" _extra="0xFFFFFFFF" _id="856572" _value="De nada.[Timing 0.37 0.00 1]" />
<_name>0x25C84B25</_name>
</section>
<_language>english</_language>
</stringtable>
How to Convert This Style
<stringtable language='english'>
<section name='0x25C84B25'>
<string enum='0x78B5CB94' extra='0xFFFFFFFF' id='856571' value='Anladın.[Timing 0.43 0.00 1]'></string>
<string enum='0xA980AB0A' extra='0xFFFFFFFF' id='856572' value='De nada.[Timing 0.37 0.00 1]'></string>
</stringtable>
</section>
By using XSLT.
Input XML
<stringtable>
<section>
<string _enum="0x78B5CB94" _extra="0xFFFFFFFF" _id="856571" _value="Anladin.[Timing 0.43 0.00 1]"/>
<string _enum="0xA980AB0A" _extra="0xFFFFFFFF" _id="856572" _value="De nada.[Timing 0.37 0.00 1]"/>
<_name>0x25C84B25</_name>
</section>
<_language>english</_language>
</stringtable>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="stringtable">
<xsl:copy>
<xsl:attribute name="language">
<xsl:value-of select="_language"/>
</xsl:attribute>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="section">
<xsl:copy>
<xsl:attribute name="name">
<xsl:value-of select="_name"/>
</xsl:attribute>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="_name" />
<xsl:template match="_language" />
</xsl:stylesheet>
Output
<stringtable language="english">
<section name="0x25C84B25">
<string _enum="0x78B5CB94" _extra="0xFFFFFFFF" _id="856571" _value="Anladin.[Timing 0.43 0.00 1]" />
<string _enum="0xA980AB0A" _extra="0xFFFFFFFF" _id="856572" _value="De nada.[Timing 0.37 0.00 1]" />
</section>
</stringtable>
c# XSLT transformation
void Main()
{
const string SOURCEXMLFILE = #"e:\Temp\input.xml";
const string XSLTFILE = #"e:\Temp\Process.xslt";
const string OUTPUTXMLFILE = #"e:\temp\output.xml";
try
{
XsltArgumentList xslArg = new XsltArgumentList();
using (XmlReader src = XmlReader.Create(SOURCEXMLFILE))
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(XSLTFILE, new XsltSettings(true, true), new XmlUrlResolver());
XmlWriterSettings settings = xslt.OutputSettings.Clone();
settings.IndentChars = "\t";
// to remove BOM
settings.Encoding = new UTF8Encoding(false);
using (XmlWriter result = XmlWriter.Create(OUTPUTXMLFILE, settings))
{
xslt.Transform(src, xslArg, result, new XmlUrlResolver());
result.Close();
}
}
Console.WriteLine("File '{0}' has been generated.", OUTPUTXMLFILE);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Related
I have below node which needs to be added in xslt if not exists :-
<xsl:template name="URLSpliter">
<xsl:param name="url" />
<xsl:variable name="splitURL" select="substring-after($url, '/')" />
<xsl:if test="contains($splitURL, '/')">
<!--To call the template recursively-->
<xsl:call-template name="URLSpliter">
<xsl:with-param name="url" select="$splitURL" />
</xsl:call-template>
</xsl:if>
<xsl:if test="not(contains($splitURL, '/'))">
<xsl:value-of select="$splitURL" />
</xsl:if>
</xsl:template>
For this, first I need to check if it exists or not ?-
I have checked it through -
IEnumerable<XElement> xElements = from xmlAuthor in doc.Descendants()
let xElement = xmlAuthor.Element("URLSpliter")
where xElement != null
select xmlAuthor;
var IsUrlSplitterExists= xElements.Any();
if(IsUrlSplitterExists)
{
}
1.I want to know if its correct way or not?
If not exists (element [name="URLSpliter"]) then needs to add.
How can I add it as a first node of xslt?
To select such elements in the XSLT namespace with LINQ to XML you would use
XNamespace xsl = "http://www.w3.org/1999/XSL/Transform";
if (!doc.Root.Elements(xsl + "template").Where(t => (string)t.Attribute("name") == "URLSplitter").Any()) {
doc.Root.AddFirst(new XElement(xsl + "template", new XAttribute("name", "URLSplitter"), ...))
}
Of course, as XSLT is XML, you might as well use XSLT to manipulate your XSLT:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/Transform-alias"
exclude-result-prefixes="axsl"
version="1.0">
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:output indent="yes"/>
<xsl:param name="new-template">
<axsl:template name="URLSpliter">
<axsl:param name="url" />
<axsl:variable name="splitURL" select="substring-after($url, '/')" />
<axsl:if test="contains($splitURL, '/')">
<!--To call the template recursively-->
<axsl:call-template name="URLSpliter">
<axsl:with-param name="url" select="$splitURL" />
</axsl:call-template>
</axsl:if>
<axsl:if test="not(contains($splitURL, '/'))">
<axsl:value-of select="$splitURL" />
</axsl:if>
</axsl:template>
</xsl:param>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xsl:transform[not(xsl:template[#name = 'URLSplitter'])] | xsl:stylesheet[not(xsl:template[#name = 'URLSplitter'])]">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:copy-of select="$new-template"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/94rmq5T
I want to merge nodes of two xml files in C# or XSLT. If the Path value of Method nodes of two different xml files are same. The two Method nodes should be merged as one in the output.
Example:
File1:
<Methods>
<Method>
<ID>1234</ID>
<Name>manager</Name>
<Path>path1</Path>
</Method>
</Methods>
File2:
<Methods>
<Method>
<Path>path1</Path>
<Description>text</Description>
</Method>
</Methods>
Output:
<Methods>
<Method>
<ID>1234</ID>
<Name>manager</Name>
<Description>text</Description>
</Method>
</Methods>
Try it this way?
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:variable name="file2" select="document('file2.xml')" />
<xsl:key name="method-by-path" match="Method" use="Path" />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Method">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
<xsl:variable name="path" select="Path"/>
<!-- switch context to the other file -->
<xsl:for-each select="$file2">
<xsl:copy-of select="key('method-by-path', $path)/*[not(self::Path)]" />
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note: this does not check for duplicate nodes.
LINQ to XML is quite effective. Try
var xml1 = XDocument.Load("File1.xml");
var xml2 = XDocument.Load("File2.xml");
foreach (XElement metNode in xml1.Descendants("ID"))
{
metNode.AddAfterSelf(xml2.Descendants("Path").Where(ele => ele.Value.Equals(metNode.Parent.Element("Path").Value)).FirstOrDefault().Parent.Element("Description"));
}
I am having one XMl, I want to remove some portion of it based upon a condition.
the XML is as follows :
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<MessageID>0a9d3ba5-9025-4e24-a0de-2403a0c0919b</MessageID>
<MessageDate>2015-04-10</MessageDate>
<PPMVersion>6.0.0.0</PPMVersion>
<SchemaVersion>1.0</SchemaVersion>
</Header>
<Package xsi:type="Ritter_Sales_Template" Path="/Package/Product/Launch_Entity" BusinessID="010170" ID="a13b6861-bb32-47fa-8ef4-f0ddcc0bc134">
<Name>MOTO_pack</Name>
<Category_ID Product_Line_ID="5">5</Category_ID>
<Effective_Start_Date>2015-02-23</Effective_Start_Date>
<Available_Start_Date>2015-02-23</Available_Start_Date>
<Element_Guid>a13b6861-bb32-47fa-8ef4-f0ddcc0bc134</Element_Guid>
<Element_Type_Guid>f7e69de1-23e8-4a66-b57b-d849e989e1ce</Element_Type_Guid>
<Business_ID>010170</Business_ID>
<Product_Name>MOTO_pack</Product_Name>
<Product_To_Product xsi:type="Product_Relation" ID="38224fc0-1a65-4b8e-9985-2277c99bbebf" Pattern="Relation_Entity">
<Association_Start_Date>2015-02-23</Association_Start_Date>
<Association_End_Date>2015-04-15</Association_End_Date>
<Product xsi:type="New_Test_template" Path="/Component/Product/Launch_Entity" BusinessID="009154" ID="da80790a-0523-472c-89b0-208d919fcf73">
<Name>idea_test</Name>
<Category_ID Product_Line_ID="5">8</Category_ID>
<Effective_Start_Date>2015-02-19</Effective_Start_Date>
<Available_Start_Date>2015-02-19</Available_Start_Date>
<Element_Guid>da80790a-0523-472c-89b0-208d919fcf73</Element_Guid>
<Element_Type_Guid>0a7fb9ea-95c4-4eed-a716-ca588f8dcae8</Element_Type_Guid>
<Business_ID>009154</Business_ID>
<Product_Name>idea_test</Product_Name>
<charge_role xsi:type="Lookup_Charge_Role" ID="6920b661-63de-45a0-94d4-900a4a873632" Pattern="Lookup">
<Name>Recipient</Name>
<Description>Recipient</Description>
</charge_role>
</Product>
</Product_To_Product>
<Product_To_Product xsi:type="Product_Relation" ID="eae5a5fd-1a27-4832-bdbe-c77907a77538" Pattern="Relation_Entity">
<Association_Start_Date>2015-02-23</Association_Start_Date>
<Association_End_Date>2015-04-10</Association_End_Date>
<Product xsi:type="Component_Template" Path="/Product_Component/Component/Product/Launch_Entity" BusinessID="010169" ID="9f4a5a5b-1cb4-463b-b211-98f08fec2ce7">
<Name>Moto-g</Name>
<Category_ID Product_Line_ID="5">8</Category_ID>
<Effective_Start_Date>2015-02-22</Effective_Start_Date>
<Available_Start_Date>2015-02-23</Available_Start_Date>
<Element_Guid>9f4a5a5b-1cb4-463b-b211-98f08fec2ce7</Element_Guid>
<Element_Type_Guid>26c0d089-259b-444b-842a-e42d21dea778</Element_Type_Guid>
<Business_ID>010169</Business_ID>
<Product_Name>Moto-g</Product_Name>
<Product_To_Product xsi:type="Product_Relation" ID="96ef93fd-ba40-4628-b22a-92c03e606a89" Pattern="Relation_Entity">
<Association_Start_Date>2015-02-23</Association_Start_Date>
<Product xsi:type="New_Test_template" Path="/Component/Product/Launch_Entity" BusinessID="009154" ID="da80790a-0523-472c-89b0-208d919fcf73">
<Name>idea_test</Name>
<Category_ID Product_Line_ID="5">8</Category_ID>
<Effective_Start_Date>2015-02-19</Effective_Start_Date>
<Available_Start_Date>2015-02-19</Available_Start_Date>
<Element_Guid>da80790a-0523-472c-89b0-208d919fcf73</Element_Guid>
<Element_Type_Guid>0a7fb9ea-95c4-4eed-a716-ca588f8dcae8</Element_Type_Guid>
<Business_ID>009154</Business_ID>
<Product_Name>idea_test</Product_Name>
<charge_role xsi:type="Lookup_Charge_Role" ID="6920b661-63de-45a0-94d4-900a4a873632" Pattern="Lookup">
<Name>Recipient</Name>
<Description>Recipient</Description>
</charge_role>
</Product>
</Product_To_Product>
</Product>
</Product_To_Product>
</Package>
</Root>
in here, i want to remove the whole Product_To_Product element if the Association_End_Date with any product is past dated. for that i have written following code in which i am comparing the dates through a C# function, but i am still unable to remove the entity. please suggest where i am going wrong.
XSLT code :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:msxsl
="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:cs
="urn:cs">
<xsl:output method="xml" version="1.0" encoding="UTF‐8" indent="yes"/>
<msxsl:script language="C#" implements-prefix="cs">
<![CDATA[public static long compareDate(long Asso_End_Date)
{
DateTime date1 = new DateTime(Asso_End_Date);
DateTime date2 = DateTime.Now;
long result;
result = date2.Date.CompareTo(date1.Date);
return(result);
}]]>
</msxsl:script>
<!-- TEMPLATE #1 -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- TEMPLATE #2 -->
<xsl:template name="mode1">
<xsl:apply-templates select="Product_To_Product[Association_End_Date]"/>
</xsl:template>
<xsl:template name="mode2">
<xsl:variable name="date"/><xsl:value-of select="Product_To_Product[Association_End_Date]"/>
<xsl:choose>
<xsl:when test="cs:compareDate($date) > 0">
<xsl:call-template name='mode1'/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
There are a number of issues with your XSLT. First, as mentioned by Lingamurthy CS in comments, you have a named template, called mode2, but nothing is calling that template, so it never gets used. It should really be changed to a template match
<xsl:template match="Product_To_Product[Association_End_Date]">
Secondly, you have a problem with how you define your date variable.
<xsl:variable name="date"/>
In other words, you don't define it. It is effectively empty. The xsl:value-of that follows the variable declaration won't affect it at all. You should define it like so
<xsl:variable name="date" select="Association_End_Date"/>
Thirdly, there is a problem with your C# function itself
public static long compareDate(long Asso_End_Date)
The parameter has type long, but you are not passing in long, but a string. The function should really look like this, so it can then parse the string
public static long compareDate(string Asso_End_Date)
{
DateTime date1 = DateTime.Parse(Asso_End_Date);
DateTime date2 = DateTime.Now;
long result;
result = date2.Date.CompareTo(date1.Date);
return(result)
}
Also, you probably need to replace > with < when checking the results of the call.
Try this XSLT (also note how the mode1 template is not needed.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:cs="urn:cs">
<xsl:output method="xml" version="1.0" encoding="UTF‐8" indent="yes"/>
<msxsl:script language="C#" implements-prefix="cs">
<![CDATA[public static long compareDate(string Asso_End_Date)
{
DateTime date1 = DateTime.Parse(Asso_End_Date);
DateTime date2 = DateTime.Now;
long result;
result = date2.Date.CompareTo(date1.Date);
return(result);
}]]>
</msxsl:script>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Product_To_Product[Association_End_Date]">
<xsl:variable name="date" select="Association_End_Date"/>
<xsl:choose>
<xsl:when test="cs:compareDate($date) <= 0">
<xsl:call-template name="identity" />
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Or better still, put the condition in the template match, to simplify it like so:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:cs="urn:cs">
<xsl:output method="xml" version="1.0" encoding="UTF‐8" indent="yes"/>
<msxsl:script language="C#" implements-prefix="cs">
<![CDATA[public static long compareDate(string Asso_End_Date)
{
DateTime date1 = DateTime.Parse(Asso_End_Date);
DateTime date2 = DateTime.Now;
long result;
result = date2.Date.CompareTo(date1.Date);
return(result);
}]]>
</msxsl:script>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Product_To_Product[cs:compareDate(Association_End_Date) > 0]" />
</xsl:stylesheet>
I have two XML Files that looks like:
...........
XML File 1:
...........
<Result>
<Id>111</Id>
<Title>Result 111 title</Title>
<Description>Result 111 Description</Description>
</Result>
...........
XML File 2:
...........
<Result>
<Id>222</Id>
<Title>Result 222 title</Title>
<Description>Result 222 Description</Description>
</Result>
I have XSLT that produces a design like this:
|ID |
|Title :| |Result 111 Title|
|Description:| |Result 111 Description|
What i want is i also want to add the elements value from 2nd XML File so the design will look like this:
|ID |
|Title :| |Result 111 Title|
|Description:| |Result 111 Description|
|ID |
|Title :| |Result 222 Title|
|Description:| |Result 222 Description|
This design will be produced during the run time in C#. I have so far applied one XML to One XSLT. But this is different. How can i achieve this. Please treat "||" to be a Design of "" tag. Any help really appreciated. Thanks..! :)
Something like this (inspired by this answer):
var xslt = new XslCompiledTransform();
xslt.Load("merge.xslt", new XsltSettings{EnableDocumentFunction = true}, null );
var xmlr = XmlReader.Create("first.xml");
var xmlw = XmlWriter.Create("result.html");
var xslargs = new XsltArgumentList();
xslargs.AddParam("fileName", "", "second.xml");
xslt.Transform(xmlr, xslargs , xmlw);, xmlw);
and the xslt:
<xsl:output method="html" indent="yes"/>
<xsl:param name="fileName" select="'somefile'" />
<xsl:param name="updates" select="document($fileName)" />
<xsl:variable name="updateItems" select="$updates/*" />
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<merge>
<xsl:copy>
<xsl:apply-templates select="*" />
<xsl:apply-templates select="$updateItems" />
</xsl:copy>
</merge>
</xsl:template>
On second thought this can be achieved even easier, where you can add an arbritrary number of files to be merged.
Code
var xslt = new XslCompiledTransform();
xslt.Load("merge.xslt", new XsltSettings{EnableDocumentFunction = true}, null );
using (var xmlr = XmlReader.Create(
new StringReader(#"<files><file>first.xml</file><file>second.xml</file></files>")))
{
using (var xmlw = XmlWriter.Create("result.html"))
{
xslt.Transform(xmlr, null , xmlw);
}
}
Xslt
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="/files/file">
<xsl:apply-templates select="document(.)/*" />
</xsl:for-each>
</body>
</html>
</xsl:template>
References:
Load
Transform
I am getting an intermittent System.Xml.Xsl.XslTransformException exception in our production environment when attempting an xslt transform, unfortunately I cannot replicate this in the development environment.
The exception spits out further details:
Execution of the 'document()' function was prohibited. Use the
XsltSettings.EnableDocumentFunction property to enable it. An error
occurred at C:\path\to\file\CDS.xsl(16,3).
However the EnableDocumentFunction property is set to true in the processing code:
private void Transform()
{
var keepTrying = true;
var tryCount = 0;
const int maxRetrys = 3;
while (keepTrying)
{
try
{
var xmlResolver = new XmlUrlResolver();
using (var xmlFile = new XmlNodeReader(_xDoc))
{
var settings = new XmlReaderSettings
{
XmlResolver = xmlResolver,
ProhibitDtd = false,
DtdProcessing = DtdProcessing.Ignore
};
using (var xsl = XmlReader.Create(_xslPath, settings))
{
var xslt = new XslCompiledTransform(true);
xslt.Load(xsl, new XsltSettings { EnableDocumentFunction = true }, xmlResolver);
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb, xslt.OutputSettings))
{
xslt.Transform(xmlFile, null, writer, xmlResolver); // errors out here.
}
var xhtml = sb.ToString();
_transformedXml = xhtml;
_isTransformed = true;
xsl.Close();
}
}
keepTrying = false;
}
catch (System.Xml.Xsl.XsltException ex)
{
ExceptionPolicy.HandleException(ex, "ExceptionLogging");
tryCount++;
if (tryCount > maxRetrys)
{
keepTrying = false;
throw;
}
}
}
}
The xslt file is provided by a third party and automatically updated, so rewriting it is not an option. Here is the top of it, slightly modified for privacy reasons:
<?xml version="1.0"?>
<!--
Interaction_550.xsl : 20110916
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:example="http://www.example.com" version="1.0">
<xsl:param name="D2DSeverityFilter"></xsl:param>
<xsl:param name="D2HSeverityFilter"></xsl:param>
<xsl:param name="DocumentationFilter"></xsl:param>
<xsl:output method="html"/>
<xsl:key name="d2d_sev_level-lookup" match="example:d2d_sev_level" use="#name"/>
<xsl:key name="d2h_sev_level-lookup" match="example:d2h_sev_level" use="#name"/>
<xsl:key name="d2l_sev_level-lookup" match="example:d2l_sev_level" use="#name"/>
<xsl:key name="preg_cat-lookup" match="example:preg_cat" use="#cat"/>
<xsl:key name="doc_level-lookup" match="example:doc_level" use="#name"/>
<xsl:variable name="d2d_sev_level-top" select="document('')/*/example:d2d_sev_levels"/>
<xsl:variable name="d2h_sev_level-top" select="document('')/*/example:d2h_sev_levels"/>
<xsl:variable name="d2l_sev_level-top" select="document('')/*/example:d2l_sev_levels"/>
<xsl:variable name="doc_level-top" select="document('')/*/example:doc_levels"/>
<xsl:variable name="preg_cat-top" select="document('')/*/example:preg_cats"/>
<xsl:template match="/">
<head>
<style type="text/css">
body {
font-family : arial,sans serif,helvetica;
}
...
How can I:
fix this so that it does not happen at all?
failing that, how could I go about replicating this in dev?
Alternatively with MS XslCompiledTransform class you can use a XsltSettings class to avoid this error as it described by the error itself. from MSDN
Here is a general way to get rid of the document('')/*/someName expressions:
The original transformation is processed with a special transformation that generates an equivalent transformation that doesn't contain the document('') function call.
Then you just need to use the generated transformation.
Example:
This transformation (lets name it tA), containing document(''):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:paramDoc1>
<x>123</x>
<y>37</y>
</my:paramDoc1>
<my:paramDoc2>
<x>456</x>
<y>79</y>
</my:paramDoc2>
<xsl:variable name="vpDoc1" select="document('')/*/my:paramDoc1"/>
<xsl:variable name="vpDoc2" select="document('')/*/my:paramDoc2"/>
<xsl:template match="/*">
<xsl:value-of select="$vpDoc1/x"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="$vpDoc2/y"/>
</xsl:template>
</xsl:stylesheet>
when applied on any document, produces:
123|79
Now we process the above transformation with this one (tGen):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="a:a" exclude-result-prefixes="x">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:namespace-alias stylesheet-prefix="x"
result-prefix="xsl"/>
<xsl:variable name="vApos">'</xsl:variable>
<xsl:variable name="vSelectPrefix" select=
"concat('document(', $vApos,$vApos, ')/*/')"/>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xsl:stylesheet">
<x:stylesheet xmlns:ext="http://exslt.org/common">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</x:stylesheet>
</xsl:template>
<xsl:template match="xsl:variable">
<xsl:variable name="vSelattr" select="#select"/>
<xsl:choose>
<xsl:when test="not(starts-with(#select, $vSelectPrefix))">
<xsl:call-template name="identity"/>
</xsl:when>
<xsl:otherwise>
<x:variable name="vrtf{#name}">
<xsl:copy-of select=
"/*/*[name()
= substring-after($vSelattr, $vSelectPrefix)
]"/>
</x:variable>
<x:variable name="{#name}" select=
"ext:node-set($vrtf{#name})/*"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
The result is a new transformation (tRes), which doesn't contain expressions like document(''):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes"
indent="yes" xmlns:my="my:my" />
<xsl:strip-space elements="*" xmlns:my="my:my" />
<my:paramDoc1 xmlns:my="my:my">
<x>123</x>
<y>37</y>
</my:paramDoc1>
<my:paramDoc2 xmlns:my="my:my">
<x>456</x>
<y>79</y>
</my:paramDoc2>
<xsl:variable name="vrtfvpDoc1">
<my:paramDoc1 xmlns:my="my:my">
<x>123</x>
<y>37</y>
</my:paramDoc1>
</xsl:variable>
<xsl:variable name="vpDoc1" select="ext:node-set($vrtfvpDoc1)/*" />
<xsl:variable name="vrtfvpDoc2">
<my:paramDoc2 xmlns:my="my:my">
<x>456</x>
<y>79</y>
</my:paramDoc2>
</xsl:variable>
<xsl:variable name="vpDoc2" select="ext:node-set($vrtfvpDoc2)/*" />
<xsl:template match="/*" xmlns:my="my:my">
<xsl:value-of select="$vpDoc1/x" />
<xsl:text>|</xsl:text>
<xsl:value-of select="$vpDoc2/y" />
</xsl:template>
</xsl:stylesheet>
If we now apply this dynamically generated transformation (tRes) to any XML document, the result is exactly the same as when applying the original transformation (tA) to this document:
123|79
Therefore, we can use tGen to convert a transformation containing document('') expressions to an equivalent transformation that doesn't contain such expressions.