2

この行でエラーが発生するので、次のコードを見てください。

xslt.Transform(mydoc.CreateReader(), writer);

エラー:

ステップ イン: 非ユーザー コード 'System.Xml.Linq.XNode.CreateReader' をステップ実行します

((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 () System.Xml.Xsl.XmlILCommand.Execute で Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime) で Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime) で(オブジェクト defaultDocument、XmlResolver dataSources、XsltArgumentList argumentList、XmlWriter ライター、Boolean closeWriter) System.Xml.Xsl.XmlILCommand.Execute(XmlReader contextDocument、XmlResolver dataSources、XsltArgumentList argumentList、XmlWriter results) at System.Xml.Xsl.

これを行うと、動作します:

StringWriter sw = new StringWriter(); 
xslt.Transform(mydoc.CreateReader(),null, sw);

XmlWriter の何が間違っていますか?

クラッシュ直前の xdoc の値:

<Promotions>
  <Promotion>
    <Category>Arts &amp; Entertainment</Category>
    <Client>Client1</Client>
    <Title>Get your Free 2</Title>
  </Promotion>
  <Promotion>
    <Category>Arts &amp; Entertainment</Category>
    <Client>Client1</Client>
    <Title>Get your Free 4</Title>
  </Promotion>
  <Promotion>
    <Category>Arts &amp; Entertainment</Category>
    <Client>client1</Client>
    <Title>Get your Free 5</Title>
  </Promotion>
  <Promotion>
    <Category>Community &amp; 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>
4

5 に答える 5

2

XSLTは、完全なXMLドキュメントではなく、要素のリストを含むXMLフラグメントを生成しているようです。<Category>そして、あなたはフラグメントを空に書き込もうとしていますXDocument。XMLには常に1つのルート要素が必要なので、無効な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>
于 2010-02-02T03:34:28.673 に答える
2

LINQ to XML オブジェクト モデル (つまり、System.Xml.Linq.XDocument/XNode) にはフラグメントを表すクラスがありませんが、スタイルシートと XmlWriter を使用して XML フラグメントを作成したいように見えることが問題だと思います。

XML入力を取得すると、コードは問題なく動作します(例

<Promotions>
  <Promotion>
    <Category>Arts &amp; Entertainment</Category>
    <Client>Client1</Client>
    <Title>Get your Free 2</Title>
  </Promotion>
  <Promotion>
    <Category>Arts &amp; Entertainment</Category>
    <Client>Client1</Client>
    <Title>Get your Free 4</Title>
  </Promotion>
  <Promotion>
    <Category>Arts &amp; Entertainment</Category>
    <Client>client1</Client>
    <Title>Get your Free 5</Title>
  </Promotion>
  <Promotion>
    <Category>Community &amp; 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>

) と投稿された 2 番目のスタイルシート (例:

<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>

) 「状態 EndRootElement のトークン StartElement は、無効な XML ドキュメントになります。XML フラグメントを書き込む場合は、ConformanceLevel 設定が ConformanceLevel.Fragment または ConformanceLevel.Auto に設定されていることを確認してください。」という InvalidOperationException を取得します。C#コードのように、XmlWriterをConformanceLevel.Fragmentで別のものにラップすることでそれに対抗しようとしたと思われますが、それはうまくいかず、別の例外が発生するだけです。

私の見解では、フラグメントを XElement に追加できるはずなので、XElement インスタンスで CreateWriter() を使用する必要があります。ただし、私のテストではまだ例外がスローされるため、バグを報告しました。 https://connect.microsoft.com/VisualStudio/feedback/details/530052/xslt-stylesheet-writing-an-xml-fragment-to-an -xmlwriter-created-with-xelementinstance-createwriter-causes-nullreferenceexception

于 2010-02-02T14:09:16.707 に答える
0

コードで XML 2.0 ドキュメントを作成するつもりだったのnew XDeclaration("2.0","utf-8","true")ですか? それが問題の原因かどうかはわかりませんが、XML 2.0 が存在しないため、奇妙なことであることは確かです。完全に削除してみてください。あなたはそれを必要としないはずです。

于 2010-02-02T02:28:13.147 に答える
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()
);
于 2010-02-02T02:54:47.703 に答える
0

どこで定義しましたmydocか? きっとヌルだ。

于 2010-02-02T02:06:52.933 に答える