我有这个XML:
<?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>
这是我的转换代码:
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;
}
我得到了这个例外:
<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 <xsl:template name="compiler:generated">(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current)
at <xsl:template match="/">(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>
如何防止此问题?
XSLT 有 151 行。您最好删除指令块,直到找到问题(或至少找到问题区域)。此外,某些工具(例如 https://xsltfiddle.liberty-development.net/)将提供行号以及错误消息。
将整个代码转储到此处并期望其他人对其进行调试是不正确的做法。此外,如果没有 XML 输入,就不可能对其进行调试。
也就是说,我在 XSLT 的第 57 - 73 行看到了这一点:
<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 规范:
以下是所有错误:
- 在将子元素添加到元素后向元素添加属性;
除此之外,我没有检查您的代码。可能有更多类似或其他错误。