使用XmlCompiledTransform合并两个XPathDocuments

时间:2010-03-02 17:36:14

标签: c# xslt merge xslcompiledtransform

我不可能成为第一个这样做的人,看起来使用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>

我知道我错过了一些明显的东西,但它已经超越了令人沮丧的程度。我知道文档被添加为参数,但我找不到如何访问作为参数加载的文档的示例。

非常感谢任何帮助。请记住,上面的代码是一项正在进行中的工作,并且在数百次尝试之间进行了两次尝试,如果某些事情看起来有些奇怪,可能是因为它在尝试之间。

1 个答案:

答案 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时遇到问题,请发布两个输入样本和您想要创建的相应结果样本。