1

我是 xslt 的新手,我需要使用 xslt 将两个 xml 合并为一个。作为最初的练习,我创建了三个文件,file1.xml、file2.xml 和 transform.xslt,并弄清楚了如何通过直接运行 file1.xml 来合并它们。我是这样做的:

在 file1.xml 中:

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="transform.xslt"?>
<stuff>
    ...
</stuff>

在 file2.xml 中:

<morestuff>
   ...
</morestuff>

在 transform.xslt 中:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:custom="custom-functions">
    <xsl:output method="xml" indent="yes" version="1.0" encoding="ISO-8859-1"/>
    <xsl:variable name="file2" select="document('file2.xml')" />
    <xsl:doing-stuff>
        ...
        <!-- contains references to $file2 -->
        ...
    </xsl:doing-stuff>
</xsl:stylesheet>

但我需要能够通过我的 C# ASP.NET 代码并使用给定的 xml字符串而不是 xml文件来做到这一点。像这样:

public string MergeXmls(string xml1, string xml2){
    string mergedXml;
    var xsltPath = HttpContext.Current.Server.MapPath("transform.xslt");
    //???
    return mergedXml;
}

我怎样才能做到这一点?我知道我需要 document('file2.xml')从 transform.xslt 中删除对的引用,但我不知道从那里去哪里。

4

2 回答 2

1

这可以使用XmlPreloadedResolver类来完成。这允许您预加载将用于解析documentXSLT 中的函数的实体。

唯一需要注意的是,函数中指定的 URIdocument被视为相对于 XSLT 文档本身的基本 URI,因此您必须使用稍微复杂的方法通过 an 加载它,XmlReader以便您可以覆盖基本 URI。

public string MergeXml(string xml1, string xml2)
{
    XslCompiledTransform xslt = new XslCompiledTransform();
    XmlDocument xsltDoc = new XmlDocument();
    // Load the XSLT file through XmlReader to override the base URI.
    using( StreamReader reader = File.OpenText(HttpContext.Current.Server.MapPath("transform.xslt")) )
    using( XmlReader xmlReader = XmlReader.Create(reader, null, "file:///transform.xslt") )
    {
        xsltDoc.Load(xmlReader);
    }
    // Use XsltSettings to enable the use of the document() function.
    xslt.Load(xsltDoc, new XsltSettings(true, false), null);

    // Load the first XML file into a document
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml1);

    // Create the resolver and add the second file to it.
    XmlPreloadedResolver resolver = new XmlPreloadedResolver();
    resolver.Add(new Uri("file:///file2.xml"), xml2);

    using( StringWriter writer = new StringWriter() )
    using( XmlWriter xmlWriter = XmlWriter.Create(writer) )
    {
        // Pass the resolver to the transform
        xslt.Transform(doc, null, xmlWriter, resolver);
        return writer.ToString();
    }
}

该类XmlPreloadedResolver仅在 .Net 4.0 及更高版本中可用,但如果您使用的是早期版本,您仍然可以从中派生自定义类System.Xml.XmlResolver并自己实现类似的功能。

于 2013-05-01T22:51:57.953 回答
1

在前端网页上,我使用这样的 System.Web.UI.WebControls.Xml 对象:

<asp:Xml ID="xmlDisplay" runat="server" />

在我的函数背后的代码中将类似于:

public void MergeXmls(string xml1, string xml2)
{
    string mergedXml = "<root>" + xml1 + xml2 + "</root>;
    xmlDisplay.DocumentContent = mergedXml;
    xmlDisplay.TransformSource = Server.MapPath("transform.xslt");
}

当您加载页面时,xmlDisplay 对象将保存将数据从mergedXml 中找到的XML 字符串加载到XSLT 中的结果。

此处提供的代码示例没有解决从作为参数传递的 2 个字符串创建有效 XML 字符串的问题,它只是将这 2 个字符串连接起来,这在某些情况下可能会起作用。

然后应该调整您的 XSLT,以便数据元素的 XPath 与在 mergeXml 字符串中找到的元素的路径相匹配。XSLT 不会引用源 XML 数据文件。

希望有帮助。

于 2013-05-01T22:44:34.587 回答