首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用C#将XML转换为HTML时出现异常

使用C#将XML转换为HTML时出现异常
EN

Stack Overflow用户
提问于 2019-06-09 23:13:07
回答 1查看 110关注 0票数 0

我有这个XML:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" version="4.01"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
  <xsl:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <xsl:attribute name="lang">
        <xsl:value-of select="//Settings//LanguageCode"/>
      </xsl:attribute>
      <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
        <link rel="stylesheet" type="text/css">
          <xsl:attribute name="href">
            <xsl:value-of select="//Settings/Template/@Style"/>
          </xsl:attribute>
        </link>
        <title>
          <!--<xsl:value-of select="//Labels/ReportTitleWorksheets"/>-->
          Assignment Slips
        </title>
        <style type="text/css">
          @import url('<xsl:text>2019/</xsl:text><xsl:value-of select="//Settings/Template/@Style"/>');
        </style>
      </head>
      <body>
        <xsl:for-each select="AssignmentSlips/Page">
          <div class="containerPage">
            <xsl:if test="@PageBreakBefore=1">
              <br style="page-break-before: always;"/>
            </xsl:if>
            <xsl:for-each select="StudentSlip">
              <div class="containerSlip">
                <img alt="s89" width="323px" height="429px">
                  <xsl:attribute name="src">
                    <xsl:text>2019\</xsl:text>
                    <xsl:value-of select="//Settings/Template"/>
                  </xsl:attribute>
                </img>
                <div class="fieldName">
                  <xsl:attribute name="dir">
                    <xsl:value-of select="//Settings/Direction"/>
                  </xsl:attribute>
                  <xsl:value-of select="Student"/>
                </div>
                <div class="fieldAssisant">
                  <xsl:attribute name="dir">
                    <xsl:value-of select="//Settings/Direction"/>
                  </xsl:attribute>
                  <xsl:value-of select="Assistant"/>
                </div>
                <div class="fieldDate">
                  <xsl:attribute name="dir">
                    <xsl:value-of select="//Settings/Direction"/>
                  </xsl:attribute>
                  <xsl:value-of select="Date"/>
                </div>
                <div class="fieldCounsel">
                  <xsl:choose>
                    <xsl:when test="@ItemPosition='1'">
                      <xsl:text>1st: </xsl:text>
                    </xsl:when>
                    <xsl:when test="@ItemPosition='2'">
                      <xsl:text>2nd: </xsl:text>
                    </xsl:when>
                    <xsl:when test="@ItemPosition='3'">
                      <xsl:text>3rd: </xsl:text>
                    </xsl:when>
                  </xsl:choose>
                  <xsl:attribute name="dir">
                    <xsl:value-of select="//Settings/Direction"/>
                  </xsl:attribute>
                  <xsl:value-of select="StudyPoint"/>
                </div>

                <xsl:choose>
                  <xsl:when test="Assignment=1">
                    <div class="checkBibleReading">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=2">
                    <div class="checkInitialCall">✓</div>
                    <div class="fieldInitialCallIndex">
                      <xsl:choose>
                        <xsl:when test="@ItemPosition='1'">
                          <xsl:text>#1</xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='2'">
                          <xsl:text>#2 </xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='3'">
                          <xsl:text>#3</xsl:text>
                        </xsl:when>
                      </xsl:choose>
                    </div>
                  </xsl:when>
                  <xsl:when test="Assignment=3">
                    <div class="checkFirstReturnVisit">✓</div>
                    <div class="fieldFirstReturnVisitIndex">
                      <xsl:choose>
                        <xsl:when test="@ItemPosition='1'">
                          <xsl:text>#1</xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='2'">
                          <xsl:text>#2 </xsl:text>
                        </xsl:when>
                        <xsl:when test="@ItemPosition='3'">
                          <xsl:text>#3</xsl:text>
                        </xsl:when>
                      </xsl:choose>
                    </div>
                  </xsl:when>
                  <xsl:when test="Assignment=4">
                    <div class="checkSecondReturnVisit">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=5">
                    <div class="checkThirdReturnVisit">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=6">
                    <div class="checkBibleStudy">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=7">
                    <div class="checkTalk">✓</div>
                  </xsl:when>
                  <xsl:when test="Assignment=0">
                    <div class="checkOther">✓</div>
                    <div class="fieldOther">
                      <xsl:attribute name="dir">
                        <xsl:value-of select="//Settings/Direction"/>
                      </xsl:attribute>
                      <xsl:value-of select="Other"/>
                    </div>
                  </xsl:when>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="Location=1">
                    <div class="checkMainHall">✓</div>
                  </xsl:when>
                  <xsl:when test="Location=2">
                    <div class="checkAuxClass1">✓</div>
                  </xsl:when>
                  <xsl:when test="Location=3">
                    <div class="checkAuxClass2">✓</div>
                  </xsl:when>
                </xsl:choose>
              </div>
            </xsl:for-each>
          </div>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

这是我的转换代码:

代码语言:javascript
复制
public bool TransformXMLToHTML(string strTransformXSLPath, string strScheduleXMLPath, string strScheduleHTMLPath)
{
    try
    {
        var xmlResolver = new XmlUrlResolver();
        XsltArgumentList argsList = new XsltArgumentList();

        string strRootPath = Path.GetDirectoryName(strTransformXSLPath);

        // Read the XSL file and locate all the CSS documents that are used
        int iFileCount = 0;
        string[] lines = File.ReadAllLines(strTransformXSLPath);
        foreach (string line in lines)
        {
            if ((line).Trim().Contains("text/css"))
            {
                int iHREFIndex = line.IndexOf("href=\"");
                if (iHREFIndex != -1)
                {
                    string strCSSFile = line.Substring(iHREFIndex + 6);

                    int iQuoteIndex = strCSSFile.IndexOf("\"");
                    if (iQuoteIndex != -1)
                    {
                        strCSSFile = strCSSFile.Substring(0, iQuoteIndex);

                        // Build full path and make sure the file exists
                        string strCSSFilePath = Path.Combine(strRootPath, strCSSFile);
                        if(File.Exists(strCSSFilePath))
                        {
                            // Establish the parameter name
                            iFileCount++;
                            string strParamName = "CSSFile" + iFileCount.ToString();

                            // Read the content and attach
                            string strCSSFileContent = File.ReadAllText(strCSSFilePath);
                            argsList.AddParam(strParamName, "", strCSSFileContent);
                        }
                    }
                }
            }
        }

        // Now perform the transformation
        XslCompiledTransform transformer = new XslCompiledTransform();
        transformer.Load(strTransformXSLPath, new XsltSettings { EnableDocumentFunction = true }, xmlResolver);

        using (StreamWriter sw = new StreamWriter(strScheduleHTMLPath))
        {
            transformer.Transform(strScheduleXMLPath, argsList, sw);
        }
    }
    catch (Exception ex)
    {
        SimpleLog.Log(ex);
        return false;
    }

    return true;
}

我得到了一个例外:

代码语言:javascript
复制
<LogEntry Date="2019-06-09 16:04:59" Severity="Exception" Source="MSAToolsLibrary.MSAToolsLibraryClass.TransformXMLToHTML" ThreadId="1">
  <Exception Type="System.Xml.Xsl.XslTransformException" Source="System.Xml.Xsl.Runtime.XmlQueryOutput.ThrowInvalidStateError">
    <Message>Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added.</Message>
    <StackTrace>   at System.Xml.Xsl.Runtime.XmlQueryOutput.ThrowInvalidStateError(XPathNodeType constructorType)
   at System.Xml.Xsl.Runtime.XmlQueryOutput.ConstructInEnumAttrs(XPathNodeType rootType)
   at System.Xml.Xsl.Runtime.XmlQueryOutput.WriteStartAttribute(String prefix, String localName, String ns)
   at &lt;xsl:template name="compiler:generated"&gt;(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current)
   at &lt;xsl:template match="/"&gt;(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current)
   at Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
   at Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
   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)
   at System.Xml.Xsl.XslCompiledTransform.Transform(String inputUri, XsltArgumentList arguments, TextWriter results)
   at MSAToolsLibrary.MSAToolsLibraryClass.TransformXMLToHTML(String strTransformXSLPath, String strScheduleXMLPath, String strScheduleHTMLPath)</StackTrace>
  </Exception>
</LogEntry>

如何防止此问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-10 00:19:23

您的XSLT有151行。在找到问题(或至少是有问题的区域)之前,最好删除指令块。此外,一些工具(例如https://xsltfiddle.liberty-development.net/)将随错误消息一起提供行号。

在这里转储您的整个代码并期望其他人来调试它不是正确的做法。此外,如果没有XML输入,就不可能对其进行调试。

也就是说,我在XSLT的第57- 73行看到了以下内容:

代码语言:javascript
复制
            <div class="fieldCounsel">
              <xsl:choose>
                <xsl:when test="@ItemPosition='1'">
                  <xsl:text>1st: </xsl:text>
                </xsl:when>
                <xsl:when test="@ItemPosition='2'">
                  <xsl:text>2nd: </xsl:text>
                </xsl:when>
                <xsl:when test="@ItemPosition='3'">
                  <xsl:text>3rd: </xsl:text>
                </xsl:when>
              </xsl:choose>
              <xsl:attribute name="dir">
                <xsl:value-of select="//Settings/Direction"/>
              </xsl:attribute>
              <xsl:value-of select="StudyPoint"/>
            </div>

在这里,您将创建一个div元素并用一些文本填充它(如果其中一个测试返回true)。然后尝试添加一个属性。这是不允许的,因为您的错误消息试图告诉您:

在添加了文本、注释、pi或子元素节点之后,不能将

属性和命名空间节点添加到父元素。

这符合XSLT specification

以下都是错误:

在将子元素添加到元素之后,

  • 向元素添加属性;

我没有检查你的代码超过了这一点。可能存在更多类似或其他错误。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56515754

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档