简体   繁体   中英

Update XSL file before transform

TNT supply manifest data as XML and an XSL file to transform that data into.

The output is then a HTML file of the manifest for printing.

This it the XSL file:

https://express.tnt.com/expresswebservices-website/stylesheets/HTMLManifestRenderer.xsl

In the xsl file there is the following:

<xsl:apply-templates select="PACKAGE[position() >= 1 and position() < 4]" mode="int"/>

Which, using my extremely limited knowledge in this area, appears to stops more than 3 items being displayed in the Manifest.

I want to remove this limit. As simple as changing the "< 4" to "< 9999"

I have the following code that works:

public static string TransformXmlStringWithXslString(string xmlString, string XSLStylesheetUrl)
{
    AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);

    // process our xml
    XmlTextReader xmlTextReader = new XmlTextReader(new StringReader(xmlString));
    XPathDocument xPathDocument = new XPathDocument(xmlTextReader);

    XsltSettings settings = new XsltSettings(true, true);

    // process the xsl
    XmlTextReader xmlTextReaderXslt = new XmlTextReader(XSLStylesheetUrl);
    XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
    xslCompiledTransform.Load(xmlTextReaderXslt, settings, new XmlUrlResolver());

    // handle the output stream
    StringBuilder stringBuilder = new StringBuilder();
    TextWriter textWriter = new StringWriter(stringBuilder);

    // do the transform
    xslCompiledTransform.Transform(xPathDocument, null, textWriter);
    return stringBuilder.ToString();
}

What is the best way to update that value before pushing the XML into it?

Rather than modifying the stylesheet, consider writing an overlay stylesheet that imports the supplied stylesheet and replaces the relevant template rule:

<xsl:stylesheet ...>
<xsl:import href="existingStylesheet.xsl"/>
<xsl:param name="maxPackages" select="5"/>

<xsl:template match="CONSIGNMENT" mode="IntPacks">
<div class="row packages">
<div class="packagescolumn1">
<div class="Line100">
<font class="newheader"> Description (incl. packing and marks) </font>
</div>
</div>
<div class="packagescolumn2">
<div class="Line100">
<font class="newheader"> Dimensions (L x W x H) </font>
</div>
</div>
<div class="packagescolumn3">
<div class="Line100">
<font class="newheader"> Total Consignment Volume   </font>
<font class="newdata">
<xsl:value-of select="concat(format-number(TOTALVOLUME, '##0.000'), ' ', PACKAGE/VOLUME/@units)"/>
</font>
</div>
</div>
<xsl:apply-templates select="PACKAGE[position() >= 1 and position() &lt;= $maxPackages]" mode="int"/>
</div>
</xsl:template>

</xsl:stylesheet>

The easiest way is to load the XSL stylesheet (don't confuse it with an XML Schema!) into an XDocument and then find the element you want to change. This code find the specific element you're after and makes the change:

var xslNS = (XNamespace) "http://www.w3.org/1999/XSL/Transform";
    
var xdoc = XDocument.Load(@"https://express.tnt.com/expresswebservices-website/stylesheets/HTMLManifestRenderer.xsl");
var xelement = xdoc
    .Descendants(xslNS + "apply-templates")
    .Where(e => (string) e.Attribute("select") == "PACKAGE[position() >= 1 and position() < 4]" 
       && (string) e.Attribute("mode") == "int");
var apply = xelement.First();
apply.SetAttributeValue("select", "PACKAGE[position() >= 1 and position() < 9999]");    

You can then use the CreateReader method on the XDocument instance to get the reader that you need to get a Compiled XSL. Incorperating that in your code it would look like this:

public static string TransformXmlStringWithXslString(string xmlString, string XSLStylesheetUrl)
{
     AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);

     // process our xml
     XmlTextReader xmlTextReader = new XmlTextReader(new StringReader(xmlString));
     XPathDocument xPathDocument = new XPathDocument(xmlTextReader);

     XsltSettings settings = new XsltSettings(true, true);

     // process the xsl
     var xslNS = (XNamespace) "http://www.w3.org/1999/XSL/Transform";
     
     var xdoc = XDocument.Load(XSLStylesheetUrl);
     var xelement = xdoc
         .Descendants(xslNS +"apply-templates")
         .Where(e => (string) e.Attribute("select") == "PACKAGE[position() >= 1 and position() < 4]" 
            && (string) e.Attribute("mode") == "int");
     var apply = xelement.First();
     apply.SetAttributeValue("select", "PACKAGE[position() >= 1 and position() < 9999]");
     
     XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
     xslCompiledTransform.Load(xdoc.CreateReader(), settings, new XmlUrlResolver());

     // handle the output stream
     StringBuilder stringBuilder = new StringBuilder();
     TextWriter textWriter = new StringWriter(stringBuilder);

     // do the transform
     xslCompiledTransform.Transform(xPathDocument, null, textWriter);
     return stringBuilder.ToString();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM