Domanda

Non posso essere la prima persona a farlo, sembra che sarebbe una pratica così comune unire due documenti usando XSLT. Tuttavia, non riesco a trovare un singolo esempio sul vecchio interweb.

Ho due documenti XML che vengono recuperati come stringhe di XML da SQL Server. Voglio usare XslCompiledTransform unire i due documenti. So che XslCompiledTransform Spegni l'XSL document() funzione per impostazione predefinita. L'ho accennato usando XsltSettings Quando creo il mio XslCompiledTransform oggetto.

La mia comprensione su come "aggiungere" il secondo documento alla trasformazione è usare un XsltArgumentList e usa il AddParam() metodo e aggiungere un XPathNavigator oggetto:

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

Tuttavia, qualsiasi tentativo di accedere al documento aggiunto risulta in un errore o nulla restituito. - 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: accede solo al documento aggiunto, non al documento caricato con la trasformazione.

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

So che mi manca qualcosa di ovvio, ma sta andando oltre il frustrante. So che il documento viene aggiunto come parametro, ma non riesco a trovare un esempio di come accedere a un documento caricato come parametro.

Qualsiasi aiuto sarebbe molto apprezzato. Tieni presente che il codice sopra è un lavoro in corso ed è tra due delle centinaia di tentativi di farlo funzionare, quindi se qualcosa sembra un po 'strano, è probabilmente perché è tra i tentativi.

È stato utile?

Soluzione

È necessario definire un parametro nel foglio di stile e quindi utilizzare quel parametro. Ecco un semplice esempio, il foglio di stile sembra segue:

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

Il codice C# sembra segue:

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

Questa è un'applicazione della console che per la semplicità scrive a Console.out ma è possibile utilizzare altri output che il metodo di trasformazione consente.

Quell'esempio quindi scrive <ul><li>1</li><li>2</li></ul> Quindi il parametro di input è stato elaborato.

Ciò dovrebbe mostrarti come passare in un parametro che XSLCompleDTransform vede come un set di nodi che puoi elaborare con XSLT.

Per quanto riguarda la scrittura di un foglio di stile che unisce due documenti, pubblica due campioni di input e il campione di risultati corrispondenti che si desidera creare se si hanno problemi a scrivere quella XSLT.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top