Ammending XSLT using XmlDocument, XmlNamespaceManager, prefix not preserved
I'm writing a function which accepts a Dataset and outputs Excel-XML ( http://msdn.microsoft.com/en-us/library/aa140066(v=office.10).aspx )
To ensure Datetime and integer fields are not treated as strings, I'm trying to edit the XLST using the XmlDocument class. I want to add something like this:
<Cell>
<Data ss:Type="String">
<xsl:value-of select="local-name()"/>
</Data>
</Cell>
to the <xsl:temp开发者_如何学运维late which matches each row.
EDIT: Code now at http://pastebin.com/r2Rea4Jw
Excel.xsl at http://pastebin.com/abkKCPmh
THE PROBLEM The xsl:value-of loses its xsl: prefix in the output, whilst ss:DataType is outputted fine.
Use http://msdn.microsoft.com/en-us/library/c22k3d47.aspx e.g. xDoc.createElement("xsl", "value-of", "http://www.w3.org/1999/XSL/Transform")
if you want to create an XSLT xsl:value-of
element node.
[edit]For me that overload works fine, to give you are more complete example, when XMLFile1.xml is
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0"
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*/*">
<Row/>
</xsl:template>
</xsl:stylesheet>
then the following C# code
XmlDocument sheet = new XmlDocument();
sheet.Load(@"..\..\XMLFile1.xml");
sheet.Save(Console.Out);
Console.WriteLine();
const string ss = "urn:schemas-microsoft-com:office:spreadsheet";
const string xsl = "http://www.w3.org/1999/XSL/Transform";
XmlNamespaceManager mgr = new XmlNamespaceManager(sheet.NameTable);
mgr.AddNamespace("ss", ss);
mgr.AddNamespace("xsl", xsl);
XmlNode row = sheet.SelectSingleNode("/xsl:stylesheet/xsl:template[@match = '/*/*']/ss:Row", mgr);
Console.WriteLine(row.OuterXml);
XmlNode cell = row.AppendChild(sheet.CreateElement("Cell", ss));
XmlNode data = cell.AppendChild(sheet.CreateElement("Data", ss));
XmlAttribute type = sheet.CreateAttribute("ss", "Type", ss);
type.Value = "String";
data.Attributes.Append(type);
XmlElement valueOf = data.AppendChild(sheet.CreateElement("xsl", "value-of", xsl)) as XmlElement;
valueOf.SetAttribute("select", "local-name()");
sheet.Save(Console.Out);
Console.WriteLine();
XslCompiledTransform proc = new XslCompiledTransform();
proc.Load(sheet);
compiles and runs just fine and outputs
<?xml version="1.0" encoding="ibm850"?>
<xsl:stylesheet version="1.0" xmlns="urn:schemas-microsoft-com:office:spreadshee
t" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*/*">
<Row />
</xsl:template>
</xsl:stylesheet>
<Row xmlns="urn:schemas-microsoft-com:office:spreadsheet" />
<?xml version="1.0" encoding="ibm850"?>
<xsl:stylesheet version="1.0" xmlns="urn:schemas-microsoft-com:office:spreadshee
t" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*/*">
<Row>
<Cell>
<Data ss:Type="String">
<xsl:value-of select="local-name()" />
</Data>
</Cell>
</Row>
</xsl:template>
</xsl:stylesheet>
Solution so far:
- Use XmlNamespaceManager
- Change local-name() to field name as template is now at row level not cell.
- add "Cell" element using same base xmlns as root element to avoid xmlns=""
- Capture intermediate forms of each XMLDocument for debugging...
精彩评论