我的C#程序必须生成不同版本的不同PDF文档。基本页眉和页脚是相同的。所以我想将它们放在一个单独的xsl中。
这里是我喜欢的文件夹结构:
/common/headerFooter.xsl
/docVersion1/doc1.xsl
/docVersion1/doc2.xsl
...
/docVersion2/doc1a.xsl
/docVersion2/doc2a.xsl
...
所以实际上包含在例如doc1.xsl应该像:
<xsl:include href="../common/headerFooter.xsl"/>
但是我收到以下错误:
[Fatal Error] :1:1 Content is not allowed in prolog.
System-ID unknown; Zeilennummer1; Spaltennummer1; org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
好的 - 第一个想法是关于BOM等,但没有。文件完全没问题(!)。
所以我试了一下:
/docVersion1/headerFooter.xsl
/docVersion1/doc1.xsl
/docVersion1/doc2.xsl
...
/docVersion2/headerFooter.xsl
/docVersion2/doc1a.xsl
/docVersion2/doc2a.xsl
...
在doc1.xsl(等)中:
<xsl:include href="headerFooter.xsl"/>
这个功能......(!?!?)
问题出在哪里?
第一次尝试的相对路径是正确的。 Visual Studio也告诉它。我认为在每个docVersion文件夹中放置headerFooter.xsl的副本会很奇怪。
最近的代码:
// xmlToPdfInfo holds all important information about the stylesheets.
// xmlToPdfInfo.XslPath : path to the doc_.xsl-files
java.io.File xsltfile = new java.io.File(xmlToPdfInfo.XslPath);
StreamSource streamSource = new StreamSource(xsltfile.getAbsoluteFile());
// ERROR LINE:
Transformer transformer = factory.newTransformer(streamSource);
// It seems there is already an analyse for all includes and it fails to
// get the relativ path correctly.
// No chance to put additional information e.g. about the path using
// parameters.
// Set the value of a <param> in the stylesheet);
if (xmlToPdfInfo.Arguments != null)
{
IList keys = xmlToPdfInfo.Arguments.GetKeyList();
foreach (var key in keys)
{
Object value = xmlToPdfInfo.Arguments[key];
try
{
transformer.setParameter(key.ToString(), value);
}
catch (Exception spe)
{
Console.WriteLine(spe.Message);
}
}
}
提醒:将headerFooter.xsl放在docVersion文件夹中都可以。退步(.../)似乎存在问题。
答案 0 :(得分:0)
最后我自己得到了答案:
重点是写自己的URIResolver!这是我的版本/方式:
public void createPDF(...) {
...
xmlToPdfInfo.Resolver = new XmlResourceResolver(...);
xmlToPdfInfo.XslPath = getPathToMyStyleSheet();
xmlToPdfInfo.IncludedDocsList = GetIncludedDocsList();
Utils.XmlToPdf(xmlToPdfInfo, outputStream);
}
protected SortedList GetIncludedDocsList()
{
SortedList sortedList = new SortedList();
sortedList.Add("headerFooter.xsl", BasePath() + ".common.headerFooter.xsl");
...
return sortedList;
}
public class Utils
{
private static XmlResourceResolver resolver;
private static SortedList includedDocsList;
/// <summary>Gets a PDF as stream from an xml-file, rendered by an xsl stylesheet</summary>
/// <param name="xmlToPdfInfo">Contains all input information</param>
/// <param name="outputStream">resulting PDF as a stream</param>
public static void XmlToPdf(XmlToPdfInfo xmlToPdfInfo, OutputStream outputStream)
{
resolver = xmlToPdfInfo.Resolver;
includedDocsList = xmlToPdfInfo.IncludedDocsList;
...
}
public class VgUriResolver : URIResolver
{
/// <summary>Gets the embedded file for the UriResolver</summary>
/// <param name="href">relative path to the file (the path that has been put in <xsl:include>)</param>
/// <param name="baseUri">base path</param>
/// <returns>The embedded source </returns>
public Source resolve(String href, String baseUri)
{
if (includedDocsList != null)
{
IList keys = includedDocsList.GetKeyList();
String hrefFilename = Path.GetFileName(href);
foreach (var key in keys)
{
String pfad = (string) includedDocsList[key];
String filename = (String) key;
try
{
// "hard-match": if by chance we can get the file
// by the real resource path.
if (pfad.Equals(href))
{
byte[] bArr = ReadToEnd(resolver.GetManifestResourceStream(pfad));
return new StreamSource(new ByteArrayInputStream(bArr));
}
// "soft-match": looks for the filenames without any path.
// Attention: works only fine if you **don't** have to include files
// with same name (different path)
if (filename.Equals(hrefFilename))
{
byte[] bArr = ReadToEnd(resolver.GetManifestResourceStream(pfad));
return new StreamSource(new ByteArrayInputStream(bArr));
}
}
catch (Exception)
{
try
{
return readFromFileStream(href);
}
catch (Exception)
{
return readFromFileStream(hrefFilename);
}
}
}
}
return new StreamSource(new StringReader(href));
}
}
}
事实上,您所写的内容更多是使用自己的URIResolver查找真实文件的键/占位符。
嗯...