Pergunta

Não posso ser a primeira pessoa a fazer isso, parece que seria uma prática tão comum mesclar dois documentos usando o XSLT. No entanto, não consigo encontrar um único exemplo no Ol 'Interweb.

Eu tenho dois documentos XML que estão sendo recuperados como strings de XML do SQL Server. Eu quero usar XslCompiledTransform para mesclar os dois documentos. eu sei que XslCompiledTransform desliga o xsl document() função por padrão. Eu ligei isso ao usar XsltSettings Quando eu crio meu XslCompiledTransform objeto.

Meu entendimento sobre como "adicionar" o segundo documento à transformação é usar um XsltArgumentList e use o AddParam() método e adicione um XPathNavigator objeto:

XsltArgumentList xsltArgs = new XsltArgumentList();
xsltArgs.AddParam(
  (string)e.UserState + "s", "http://www.myuri.com/tabledata", 
  dataXmlDoc.CreateNavigator()
);

No entanto, qualquer tentativa de acessar o documento que é adicionado resulta em um erro ou nada devolvido. - 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 - acessa apenas o documento adicionado, não o documento carregado com a transformação.

<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>

Eu sei que estou perdendo algo óbvio, mas está ficando além de frustrante. Sei que o documento é adicionado como um parâmetro, mas não consigo encontrar um exemplo de como acessar um documento carregado como um parâmetro.

Qualquer ajuda seria muito apreciada. Lembre -se de que o código acima é um trabalho em andamento e está entre duas das centenas de tentativas de fazê -lo funcionar, portanto, se algo parecer um pouco estranho, provavelmente é porque está entre as tentativas.

Foi útil?

Solução

Você precisa definir um parâmetro na sua folha de estilo e, em seguida, usar esse parâmetro. Aqui está um exemplo simples, a folha de estilo parece o seguinte:

<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>

O código C# parece o seguinte:

    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);

Este é um aplicativo de console que, por simplicidade, grava para consolar.out, mas é claro que você pode usar outras saídas que o método de transformação permite.

Esse exemplo então escreve <ul><li>1</li><li>2</li></ul> Portanto, o parâmetro de entrada foi processado.

Portanto, isso deve mostrar como passar em um parâmetro que o XSLCompiledTransform vê como um conjunto de nós que você pode processar com o XSLT.

Quanto a escrever uma folha de estilo que mescla dois documentos, publique duas amostras de entrada e a amostra de resultado correspondente que você deseja criar se tiver problemas para escrever esse XSLT.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top