我不可能成为第一个这样做的人,看起来使用XSLT合并两个文档似乎是一种常见的做法。但是,我似乎无法在ol'interweb上找到一个例子。
我有两个XML文档,它们是从SQL Server中作为XML字符串检索的。我想使用XslCompiledTransform
合并这两个文档。我知道XslCompiledTransform
默认关闭了XSL document()
函数。我在创建XsltSettings
对象时使用XslCompiledTransform
转向了这一点。
我对如何将第二个文档“添加”到转换中的理解是使用XsltArgumentList
并使用AddParam()
方法并添加XPathNavigator
对象:
XsltArgumentList xsltArgs = new XsltArgumentList();
xsltArgs.AddParam(
(string)e.UserState + "s", "http://www.myuri.com/tabledata",
dataXmlDoc.CreateNavigator()
);
但是,任何尝试访问添加的文档都会导致错误或返回任何内容。 - C#:
XslCompiledTransform fieldToXhtmlTransform = new XslCompiledTransform(true);
try
{
UriBuilder xsltUri = new UriBuilder(
Request.Url.Scheme, Request.Url.Host,
Request.Url.Port, this.ResolveUrl("Transforms/address1.xslt")
);
XmlSecureResolver resolver = new XmlSecureResolver(
new XmlUrlResolver(), new PermissionSet(PermissionState.Unrestricted)
);
fieldToXhtmlTransform.Load(
xsltUri.ToString(), new XsltSettings(true, false), resolver
);
}
catch
{
//TODO: do something useful here.
}
XPathDocument fieldSchemaXmlDoc = null;
using (MemoryStream fieldMemoryStream = new MemoryStream(
Encoding.UTF8.GetBytes(e.Result.TableMetaDataXml)
))
{
fieldSchemaXmlDoc = new XPathDocument(fieldMemoryStream);
}
XPathDocument dataXmlDoc = null;
using (MemoryStream dataMemoryStream = new MemoryStream(
Encoding.UTF8.GetBytes(e.Result.DataXml)
))
{
dataXmlDoc = new XPathDocument(dataMemoryStream);
}
StringBuilder output = new StringBuilder();
XmlWriterSettings writerSettings = new XmlWriterSettings();
writerSettings.OmitXmlDeclaration = true;
writerSettings.Encoding = Encoding.UTF8;
XsltArgumentList xsltArgs = new XsltArgumentList();
xsltArgs.AddParam(
(string)e.UserState + "s", "http://www.myuri.com/tabledata",
dataXmlDoc.CreateNavigator()
);
XmlWriter transformedDataWriter = XmlWriter.Create(output, writerSettings);
fieldToXhtmlTransform.Transform(
fieldSchemaXmlDoc, xsltArgs, transformedDataWriter
);
XSLT - 仅访问添加的文档,而不是加载转换的文档。
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:hlsschema="http://www.myuri.com/tableschema"
xmlns:hlsdata="http://www.myuri.com/tabledata"
exclude-result-prefixes="msxsl hlsschema hlsdata xsl"
>
<xsl:output method="html" indent="yes"/>
<p>
<xsl:template match="hlsdata:Address1s">
<xsl:for-each select="hlsdata:Address1">
<p>
<xsl:value-of select="hlsdata:dr_id"/>
</p>
</xsl:for-each>
</xsl:template>
</p>
</xsl:stylesheet>
XML
<hlsdata:Address1s
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:hlsdata="http://www.myuri.com/tabledata"
>
<hlsdata:Address1>
<hlsdata:dr_id>12345678</hlsdata:dr_id>
</hlsdata:Address1>
</hlsdata:Address1s>
我知道我错过了一些明显的东西,但它已经超越了令人沮丧的程度。我知道文档被添加为参数,但我找不到如何访问作为参数加载的文档的示例。
非常感谢任何帮助。请记住,上面的代码是一项正在进行中的工作,并且在数百次尝试之间进行了两次尝试,如果某些事情看起来有些奇怪,可能是因为它在尝试之间。
答案 0 :(得分:4)
您需要在样式表中定义参数,然后使用该参数。 这是一个简单的例子,样式表如下所示:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:docs="http://example.com/2010/docs"
exclude-result-prefixes="docs"
>
<xsl:param name="docs:doc1" select="/.."/>
<xsl:template match="/">
<xsl:apply-templates select="$docs:doc1/node()"/>
</xsl:template>
<xsl:template match="root">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="foo">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
</xsl:stylesheet>
C#代码如下所示:
string xml = "<root><foo>1</foo><foo>2</foo></root>";
XPathDocument doc = new XPathDocument(new StringReader(xml));
XslCompiledTransform proc = new XslCompiledTransform();
proc.Load(@"..\..\XSLTFile1.xslt");
XsltArgumentList xsltArgs = new XsltArgumentList();
xsltArgs.AddParam("doc1", "http://example.com/2010/docs", doc.CreateNavigator());
proc.Transform(XmlReader.Create(new StringReader("<dummy/>")), xsltArgs, Console.Out);
这是一个控制台应用程序,为简单起见,写入Console.Out,但您当然可以使用Transform方法允许的其他输出。
然后该示例写入<ul><li>1</li><li>2</li></ul>
,以便处理输入参数。
因此,应该向您展示如何将XslCompiledTransform看到的参数传递给您可以使用XSLT处理的节点集。
至于编写合并两个文档的样式表,如果您在编写XSLT时遇到问题,请发布两个输入样本和您想要创建的相应结果样本。