Объединение двух xpathdocuments с использованием xmlcompiledtransform
-
23-09-2019 - |
Вопрос
Я не могу быть первым, кто это сделал, кажется, что было бы такой обычной практикой объединять два документа с использованием XSLT. Тем не менее, я не могу найти ни одного примера на Ol 'Interweb.
У меня есть два XML -документа, которые получаются как строки XML с SQL Server. Я хочу использовать 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>
Я знаю, что упускаю что -то очевидное, но это выходит за рамки разочарования. Я знаю, что документ добавляется в качестве параметра, но я не могу найти пример того, как получить доступ к документу, загруженный как параметр.
Любая помощь будет очень оценена. Имейте в виду, что приведенный выше код находится в стадии разработки и находится между двумя из сотен попыток заставить его работать, поэтому, если что -то выглядит немного странно, это, вероятно, потому, что между попытками.
Решение
Вам нужно определить параметр в своей таблице стилей, а затем использовать этот параметр. Вот простой пример, таблица стиля выглядит следующим образом:
<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, но вы, конечно, можете использовать другие выходы, которые позволяет метод преобразования.
Этот пример затем пишет <ul><li>1</li><li>2</li></ul>
Таким образом, входной параметр был обработан.
Так что это должно показать вам, как пройти в параметре, который XslCompiledTransform считает как набор узлов, который вы можете обработать с помощью XSLT.
Что касается написания таблицы стилей, которая объединяет два документа, пожалуйста, опубликуйте два образца ввода и соответствующий образец результатов, который вы хотите создать, если у вас есть проблемы с написанием этого XSLT.