无法让 xsl:import 或 xsl:include 在 MSXML6 上工作
Can't get xsl:import or xsl:include to work on MSXML6
我正在尝试让 MSXML6 XSLT 导入(或包含)功能适用于我的应用程序。我到处寻找解决这个问题的方法,并找到了很多人的参考资料,这些人似乎对他们有用,所以我想我一定是做错了什么,但我不知道是什么。
Book.xml
<Book>
<Title>A Christmas Carol</Title>
<Author>Charles Dickens</Author>
<Binding>Hardcover</Binding>
<Price>14.99</Price>
<Comment/>
</Book>
DefaultRules.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="/Temp/Book.xsl"/>
<xsl:output method="text" indent="no"/>
<xsl:template match="/">
<xsl:apply-templates select="Book"/>
</xsl:template>
</xsl:stylesheet>
Book.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Book">
<xsl:text>Title: </xsl:text>
<xsl:apply-templates select="Title"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="Author"/>
<xsl:text> - $</xsl:text>
<xsl:apply-templates select="Price"/>
</xsl:template>
</xsl:stylesheet>
Proto.cpp
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
variant_t vResult;
LPCTSTR output = NULL;
MSXML2::IXMLDOMDocumentPtr pXml(__uuidof(MSXML2::DOMDocument60));
MSXML2::IXMLDOMDocumentPtr pXslt(__uuidof(MSXML2::FreeThreadedDOMDocument60));
MSXML2::IXSLTemplatePtr pTemplate(__uuidof(MSXML2::XSLTemplate60));
MSXML2::IXSLProcessorPtr pProcessor;
IStream *pOutStream;
// load xml file with data and xsl file to transform
// xml -> html
pXml->async = false;
pXml->load(_bstr_t("Book.xml"));
pXslt->resolveExternals = true;
pXslt->async = false;
pXslt->load(_bstr_t("/Temp/DefaultRules.xsl"));
pTemplate->stylesheet = pXslt;
pProcessor = pTemplate->createProcessor();
CreateStreamOnHGlobal(NULL, TRUE, &pOutStream);
pProcessor->put_output(_variant_t(pOutStream));
pProcessor->put_input(_variant_t((IUnknown*)pXml));
pProcessor->transform();
//get results of transformation and print them to stdout
HGLOBAL hg = NULL;
pOutStream->Write((void const*)"[=15=][=15=]", 2, 0);
GetHGlobalFromStream(pOutStream, &hg);
output = (LPCTSTR)GlobalLock(hg);
wprintf(L"%s", output);
GlobalUnlock(hg);
//release before CoUninitialize()
pXml.Release();
pXslt.Release();
pTemplate.Release();
pProcessor.Release();
CoUninitialize();
getchar();
return 0;
}
我从 XML 工具 (EditiX) 得到的(正确)输出是
Title: A Christmas Carol
Charles Dickens - .99
我从 MSXML6 转换得到的(不正确的)输出是
A Christmas CarolCharles DickensHardcover14.99
看起来指定要包含的文件不是 imported/included 所以我只是得到默认模板结果,尽管我没有收到任何错误消息。如您所见,我将 resolveExternals 标志设置为 true(MSXML6 的新标志)。我还尝试从当前文件夹以及特定文件夹(上面的代码使用/Temp)加载它。我也尝试过同时使用 xsl:import 和 xsl:include。该解决方案在 XML 工具中始终有效,但使用上述代码和 MSXML6 总是给出不正确的结果。如果可能相关,我正在使用 Windows 10。
我认为问题是你设置了pXslt->resolveExternals = true;
,你需要使用pXslt->resolveExternals = VARIANT_TRUE;
。
我正在尝试让 MSXML6 XSLT 导入(或包含)功能适用于我的应用程序。我到处寻找解决这个问题的方法,并找到了很多人的参考资料,这些人似乎对他们有用,所以我想我一定是做错了什么,但我不知道是什么。
Book.xml
<Book>
<Title>A Christmas Carol</Title>
<Author>Charles Dickens</Author>
<Binding>Hardcover</Binding>
<Price>14.99</Price>
<Comment/>
</Book>
DefaultRules.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="/Temp/Book.xsl"/>
<xsl:output method="text" indent="no"/>
<xsl:template match="/">
<xsl:apply-templates select="Book"/>
</xsl:template>
</xsl:stylesheet>
Book.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Book">
<xsl:text>Title: </xsl:text>
<xsl:apply-templates select="Title"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="Author"/>
<xsl:text> - $</xsl:text>
<xsl:apply-templates select="Price"/>
</xsl:template>
</xsl:stylesheet>
Proto.cpp
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
variant_t vResult;
LPCTSTR output = NULL;
MSXML2::IXMLDOMDocumentPtr pXml(__uuidof(MSXML2::DOMDocument60));
MSXML2::IXMLDOMDocumentPtr pXslt(__uuidof(MSXML2::FreeThreadedDOMDocument60));
MSXML2::IXSLTemplatePtr pTemplate(__uuidof(MSXML2::XSLTemplate60));
MSXML2::IXSLProcessorPtr pProcessor;
IStream *pOutStream;
// load xml file with data and xsl file to transform
// xml -> html
pXml->async = false;
pXml->load(_bstr_t("Book.xml"));
pXslt->resolveExternals = true;
pXslt->async = false;
pXslt->load(_bstr_t("/Temp/DefaultRules.xsl"));
pTemplate->stylesheet = pXslt;
pProcessor = pTemplate->createProcessor();
CreateStreamOnHGlobal(NULL, TRUE, &pOutStream);
pProcessor->put_output(_variant_t(pOutStream));
pProcessor->put_input(_variant_t((IUnknown*)pXml));
pProcessor->transform();
//get results of transformation and print them to stdout
HGLOBAL hg = NULL;
pOutStream->Write((void const*)"[=15=][=15=]", 2, 0);
GetHGlobalFromStream(pOutStream, &hg);
output = (LPCTSTR)GlobalLock(hg);
wprintf(L"%s", output);
GlobalUnlock(hg);
//release before CoUninitialize()
pXml.Release();
pXslt.Release();
pTemplate.Release();
pProcessor.Release();
CoUninitialize();
getchar();
return 0;
}
我从 XML 工具 (EditiX) 得到的(正确)输出是
Title: A Christmas Carol
Charles Dickens - .99
我从 MSXML6 转换得到的(不正确的)输出是
A Christmas CarolCharles DickensHardcover14.99
看起来指定要包含的文件不是 imported/included 所以我只是得到默认模板结果,尽管我没有收到任何错误消息。如您所见,我将 resolveExternals 标志设置为 true(MSXML6 的新标志)。我还尝试从当前文件夹以及特定文件夹(上面的代码使用/Temp)加载它。我也尝试过同时使用 xsl:import 和 xsl:include。该解决方案在 XML 工具中始终有效,但使用上述代码和 MSXML6 总是给出不正确的结果。如果可能相关,我正在使用 Windows 10。
我认为问题是你设置了pXslt->resolveExternals = true;
,你需要使用pXslt->resolveExternals = VARIANT_TRUE;
。