请查看以下代码,因为我在此行收到错误:
xslt.Transform(mydoc.CreateReader(), writer);
错误:
单步执行:单步执行非用户代码'System.Xml.Linq.XNode.CreateReader' System.Data.SqlXml.dll中发生了'System.NullReferenceException'类型的第一次机会异常
((System.NullReferenceException)(前))
PromotionsDataContext db = new PromotionsDataContext();
//XmlDocument myxml;
XElement Categories =
new XElement("Promotions",
from b in db.GetPromotions()
select new XElement("Promotion",
new XElement("Category", b.CategoryName),
new XElement("Client", b.ClientName),
new XElement("Title", b.Title)));
XDocument mydoc = new XDocument();
mydoc.Add(Categories);
try
{
XDocument newTree = new XDocument();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.CloseOutput = false;
//using (XmlWriter writer = newTree.CreateWriter())
using (XmlWriter writer = XmlWriter.Create(newTree.CreateWriter(), settings))
{
// Load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(XmlReader.Create(new FileStream(@"C:\1\TransList.xslt", System.IO.FileMode.Open)));
// Execute the transform and output the results to a writer.
xslt.Transform(mydoc.CreateReader(), writer);
}
Console.WriteLine(newTree);
}
catch (Exception ex)
{
Console.Write(ex);
}
这是XSLT:
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method='xml' />
<xsl:key name='categories' match='Category' use='.' />
<xsl:template match='/'>
<xsl:for-each select="/Promotions/Promotion/Category[
generate-id(.) = generate-id(key('categories', .)[1])
]">
<xsl:variable name='cname' select='.' />
<Category title='{.}'>
<xsl:for-each select='/Promotions/Promotion[Category=$cname]'>
<Title>
<xsl:value-of select='Title' />
</Title>
</xsl:for-each>
</Category>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
错误:
System.NullReferenceException:未将对象引用设置为对象的实例。 在System.Xml.Xsl.Runtime.XmlMergeSequenceWriter.StartTree(XPathNodeType rootType,IXmlNamespaceResolver nsResolver,XmlNameTable nameTable) 在System.Xml.Xsl.Runtime.XmlQueryOutput.StartTree(XPathNodeType rootType) 在System.Xml.Xsl.Runtime.XmlQueryOutput.WriteStartRoot() 在Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}运行时) at Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug} runtime) 在System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument,XmlResolver dataSources,XsltArgumentList argumentList,XmlWriter writer,Boolean closeWriter) 在System.Xml.Xsl.XmlILCommand.Execute(XmlReader contextDocument,XmlResolver dataSources,XsltArgumentList argumentList,XmlWriter结果) 在System.Xml.Xsl.XslCompiledTransform.Transform(XmlReader输入,XsltArgumentList参数,XmlWriter结果) at Promo.Page_Load(Object sender,EventArgs e)在c:\ 1 \ promo.ascx.cs:第144行
现在,如果我这样做,它可以工作:
StringWriter sw = new StringWriter();
xslt.Transform(mydoc.CreateReader(),null, sw);
我在使用XmlWriter时遇到了什么问题?
崩溃前xdoc的值:
<Promotions>
<Promotion>
<Category>Arts & Entertainment</Category>
<Client>Client1</Client>
<Title>Get your Free 2</Title>
</Promotion>
<Promotion>
<Category>Arts & Entertainment</Category>
<Client>Client1</Client>
<Title>Get your Free 4</Title>
</Promotion>
<Promotion>
<Category>Arts & Entertainment</Category>
<Client>client1</Client>
<Title>Get your Free 5</Title>
</Promotion>
<Promotion>
<Category>Community & Neighborhood</Category>
<Client>Client2</Client>
<Title>Get your Free 1</Title>
</Promotion>
<Promotion>
<Category>Education</Category>
<Client>Client3</Client>
<Title>Get Your Free 3</Title>
</Promotion>
</Promotions>
答案 0 :(得分:2)
看起来您的XSLT正在生成包含<Category>
元素列表的XML 片段,而不是完整的XML文档。而且您正在尝试将片段写入空XDocument
。这将导致XML文档无效,因为您始终需要XML中的一个根元素。我不知道是否具体是导致您的异常的原因,但您应该看到当您修改XSLT时会发生什么:
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method='xml' />
<xsl:key name='categories' match='Category' use='.' />
<xsl:template match='/'>
<Categories> <!-- Added a root element here -->
<xsl:for-each select="/Promotions/Promotion/Category[
generate-id(.) = generate-id(key('categories', .)[1])
]">
<xsl:variable name='cname' select='.' />
<Category title='{.}'>
<xsl:for-each select='/Promotions/Promotion[Category=$cname]'>
<Title>
<xsl:value-of select='Title' />
</Title>
</xsl:for-each>
</Category>
</xsl:for-each>
</Categories>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:2)
我认为问题确实是您似乎想要使用样式表和XmlWriter创建XML片段,而LINQ to XML对象模型(即System.Xml.Linq.XDocument / XNode)没有任何类表示片段。
如果我接受你的XML输入(例如
),代码可以完美地运行<Promotions>
<Promotion>
<Category>Arts & Entertainment</Category>
<Client>Client1</Client>
<Title>Get your Free 2</Title>
</Promotion>
<Promotion>
<Category>Arts & Entertainment</Category>
<Client>Client1</Client>
<Title>Get your Free 4</Title>
</Promotion>
<Promotion>
<Category>Arts & Entertainment</Category>
<Client>client1</Client>
<Title>Get your Free 5</Title>
</Promotion>
<Promotion>
<Category>Community & Neighborhood</Category>
<Client>Client2</Client>
<Title>Get your Free 1</Title>
</Promotion>
<Promotion>
<Category>Education</Category>
<Client>Client3</Client>
<Title>Get Your Free 3</Title>
</Promotion>
</Promotions>
)和第二个样式表(例如
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method='xml' />
<xsl:key name='categories' match='Category' use='.' />
<xsl:template match='/'>
<Categories>
<!-- Added a root element here -->
<xsl:for-each select="/Promotions/Promotion/Category[
generate-id(.) = generate-id(key('categories', .)[1])
]">
<xsl:variable name='cname' select='.' />
<Category title='{.}'>
<xsl:for-each select='/Promotions/Promotion[Category=$cname]'>
<Title>
<xsl:value-of select='Title' />
</Title>
</xsl:for-each>
</Category>
</xsl:for-each>
</Categories>
</xsl:template>
</xsl:stylesheet>
)然后使用以下C#代码:
XDocument mydoc = XDocument.Load(@"..\..\XMLFile1.xml");
XDocument newTree = new XDocument();
using (XmlWriter writer = newTree.CreateWriter())
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(@"..\..\XSLTFile2.xslt");
xslt.Transform(mydoc.CreateReader(), writer);
writer.Close();
}
Console.WriteLine(newTree);
当我使用原始样式表时(例如
)<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method='xml' />
<xsl:key name='categories' match='Category' use='.' />
<xsl:template match='/'>
<xsl:for-each select="/Promotions/Promotion/Category[
generate-id(.) = generate-id(key('categories', .)[1])
]">
<xsl:variable name='cname' select='.' />
<Category title='{.}'>
<xsl:for-each select='/Promotions/Promotion[Category=$cname]'>
<Title>
<xsl:value-of select='Title' />
</Title>
</xsl:for-each>
</Category>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
)我得到一个InvalidOperationException,说“状态EndRootElement中的Token StartElement会导致无效的XML文档。如果要编写XML片段,请确保将ConformanceLevel设置设置为ConformanceLevel.Fragment或ConformanceLevel.Auto。”我怀疑你试图用你的C#代码将你的XmlWriter包装到另一个包含ConformanceLevel.Fragment的方法来解决这个问题,但是我认为这不起作用,它只会导致一个不同的异常。
我认为应该在XElement实例上使用CreateWriter(),因为应该可以将片段添加到XElement。然而,我的测试仍然会引发异常,因此我已经提交了一个错误,请参阅https://connect.microsoft.com/VisualStudio/feedback/details/530052/xslt-stylesheet-writing-an-xml-fragment-to-an-xmlwriter-created-with-xelementinstance-createwriter-causes-nullreferenceexception
答案 2 :(得分:0)
您在哪里定义mydoc
?我打赌它是空的。
答案 3 :(得分:0)
您的意思是在new XDeclaration("2.0","utf-8","true")
代码中创建XML 2.0文档吗?我不知道是否会导致这个问题,但这确实很奇怪,因为XML 2.0不存在。尝试完全删除它;你不应该需要它。
答案 4 :(得分:0)
因为XML是通过LINQ to XML构建的,所以可以推迟执行此代码:
XElement Categories = new XElement(
"Promotions",
from b in db.GetPromotions()
select new XElement("Promotion",
new XElement("Category", b.CategoryName),
new XElement("Client", b.ClientName),
new XElement("Title", b.Title)));
您的错误可能发生在此代码中。尝试在LINQ中放置断点以逐步完成XElement创建。或者,为了确保不延迟执行,您可以执行以下操作:
XElement Categories = new XElement(
"Promotions",
(
from b in db.GetPromotions()
select new XElement("Promotion",
new XElement("Category", b.CategoryName),
new XElement("Client", b.ClientName),
new XElement("Title", b.Title))
).ToList()
);