开发者

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:

  1. Use XmlNamespaceManager
  2. Change local-name() to field name as template is now at row level not cell.
  3. add "Cell" element using same base xmlns as root element to avoid xmlns=""
  4. Capture intermediate forms of each XMLDocument for debugging...
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜