Мне нужно было преобразовать содержимое HTML веб-страницы с помощью XSLT . Поэтому я использовал SgmlReader и написал приведенный ниже фрагмент кода (в конце концов я подумал, что это XmlReader тоже...)
XmlReader xslr = XmlReader.Create(new StringReader(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" +
"<xsl:output method=\"xml\" encoding=\"UTF-8\" version=\"1.0\" />" +
"<xsl:template match=\"/\">" +
"<XXX xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><xsl:value-of select=\"count(//br)\" /></XXX>" +
"</xsl:template>" +
"</xsl:stylesheet>"));
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xslr);
using (SgmlReader html = new SgmlReader())
{
StringBuilder sb = new StringBuilder();
using (TextWriter sw = new StringWriter(sb))
using (XmlWriter xw = new XmlTextWriter(sw))
{
html.InputStream = new StringReader(Resources.html_orig);
html.DocType = "HTML";
try
{
xslt.Transform(html, xw);
string output = sb.ToString();
System.Console.WriteLine(output);
}
catch (Exception exc)
{
System.Console.WriteLine("{0} : {1}", exc.GetType().Name, exc.Message);
System.Console.WriteLine(exc.StackTrace);
}
}
}
Тем не менее, я получаю это сообщение об ошибке
NullReferenceException : Object reference not set to an instance of an object.
at MS.Internal.Xml.Cache.XPathDocumentBuilder.Initialize(XPathDocument doc, IXmlLineInfo lineInfo, String baseUri, LoadFlags flags)
at MS.Internal.Xml.Cache.XPathDocumentBuilder..ctor(XPathDocument doc, IXmlLineInfo lineInfo, String baseUri, LoadFlags flags)
at System.Xml.XPath.XPathDocument.LoadFromReader(XmlReader reader, XmlSpace space)
at System.Xml.XPath.XPathDocument..ctor(XmlReader reader, XmlSpace space)
at System.Xml.Xsl.Runtime.XmlQueryContext.ConstructDocument(Object dataSource, String uriRelative, Uri uriResolved)
at System.Xml.Xsl.Runtime.XmlQueryContext..ctor(XmlQueryRuntime runtime, Object defaultDataSource, XmlResolver dataSources, XsltArgumentList argList, WhitespaceRuleLookup wsRules)
at System.Xml.Xsl.Runtime.XmlQueryRuntime..ctor(XmlQueryStaticData data, Object defaultDataSource, XmlResolver dataSources, XsltArgumentList argList, XmlSequenceWriter seqWrt)
at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results)
at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, Boolean closeWriter)
at System.Xml.Xsl.XmlILCommand.Execute(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results)
at System.Xml.Xsl.XslCompiledTransform.Transform(XmlReader input, XmlWriter results)
Я нашел способ обойти это, преобразовав HTML в XML и затем применив преобразование, но это неэффективное решение, потому что:
- Промежуточный вывод XHTML помещается в буфер , поэтому требуется дополнительная память.
- Процесс преобразования требует дополнительной обработки CPU, и одна и та же иерархия проходится дважды (теоретически без необходимости).
Итак (поскольку я знаю, что сообщество StackOverflow всегда дает отличные ответы, в то время как другие форумы C# меня полностью разочаровали ;o), я буду ждать отзывов. и предложения по выполнению преобразований XSL с использованием HTML напрямую (даже если SgmlReader нужно заменить другой похожей библиотекой).
ReadSubtree
илиReadInnerXml
, не имеют никакого смысла. Таким образом, в случае запуска XSLT в SgmlReader вы можете столкнуться с тем, что базовый механизм вызывает один из этих методов, но не получает ожидаемого результата. Также см. комментарий Алехандро о том, что ожидается от XSLT. 02.12.2010