我使用一种专有工具,通过 Saxon 10 引擎利用 XSLT。
我正在寻找一种将有效负载从 XSL 发送到 API 端点的方法。有效负载对于 GET 来说太大了(我可以在 XSL 中完成),所以我需要它是一个 POST。
我无法使用 EXPath http 客户端扩展,但 Saxon 允许您调用 .NET 或 Java 函数。
我不是 .NET 开发人员,但我通过 Windows Workflow Foundation 使用了下面这个代码片段的变体,并且提交得很好。我想也许我可以将其转换为撒克逊友好的 XSLT 来完成同样的事情。
var url = "https://httpbin.org/post";
var client = new HttpClient;
var content = new StringContent(payload, System.Text.Encoding.UTF8,"application/json");
var response = await client.PostAsync(url, content);
我想要做的是使用 Saxon 处理 .NET 的能力来复制此类代码,但在 XSLT 样式表内。
使用 Saxonica 文档作为参考,以及我们内部的其他 XSLT 示例,我开始编写此内容:
<xsl:stylesheet
version="3.0"
xmlns:net="clitype=System.Net.Http.HttpClient"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="postTest">
<xsl:variable name="req" select="net:new()"/>
</xsl:template>
</xsl:stylesheet>
我没有进一步了解,因为即使这也报告了 Saxon 引擎的错误。
我还尝试了 ChatGPT,看看它是否能给我一些想法。它给了我类似的例子,它们也都生成“无法在...中找到 X 参数函数”。这是它给我的代码:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:net="clitype:System.Net.Http"
xmlns:encoding="clitype:System.Text.Encoding"
exclude-result-prefixes="net encoding">
<xsl:template match="/">
<xsl:variable name="url" select="'https://httpbin.org/post'" />
<xsl:variable name="client" select="net:HttpClient()" />
<!-- Prepare the payload -->
<xsl:variable name="payload" select="'nothing'" />
<xsl:variable name="content" select="net:StringContent($payload, encoding:UTF8(), 'application/json')" />
<!-- Send the POST request -->
<xsl:variable name="response" select="net:HttpClient.PostAsync($url, $content)" />
<!-- Read the response -->
<xsl:variable name="responseBody" select="net:HttpResponseMessage.Content.ReadAsStringAsync($response)" />
<!-- Output the response body -->
<xsl:message>Response:</xsl:message>
<xsl:value-of select="$responseBody"/>
</xsl:template>
</xsl:stylesheet>
这里有人有在 XSLT 或 .NET 中做类似事情的经验吗?我什至不在乎它是否是 .NET,因为 Saxon 也支持 Java。
我确实需要能够将部分 XML 数据发布到外部 API,但我无法向我的 XSLT 处理器或 Saxon 添加任何其他库。
如有任何建议,我们将不胜感激。
我摸索出了一些自反 Java 调用,这些调用至少在 Saxon EE 10.9 Java 以及执行 POST 请求的 .NET 中运行:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:BufferedReader="java:java.io.BufferedReader"
xmlns:InputStreamReader="java:java.io.InputStreamReader"
xmlns:OutputStream="java:java.io.OutputStream"
xmlns:HttpURLConnection="java:java.net.HttpURLConnection"
xmlns:URL="java:java.net.URL"
xmlns:JString="java:java.lang.String"
xmlns:Stream="java:java.util.stream.Stream"
xmlns:Charset="java:java.nio.charset.Charset"
xmlns:ByteBuffer="java:java.nio.ByteBuffer"
xmlns:StandardCharsets="java:java.nio.charset.StandardCharsets"
xmlns:jt="http://saxon.sf.net/java-type"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="payload" as="xs:string" expand-text="no">{ "Name" : "John Doe", "Age" : 42 }</xsl:param>
<xsl:param name="url" as="xs:string">https://httpbin.org/post</xsl:param>
<xsl:template name="xsl:initial-template" expand-text="yes">
<xsl:variable name="uri" as="xs:anyURI" select="xs:anyURI($url)"/>
<xsl:variable name="java-url" as="jt:java.net.URL" select="URL:new($uri)"/>
<xsl:variable name="conn" select="URL:openConnection($java-url)"/>
<xsl:message select="HttpURLConnection:setRequestMethod($conn, 'POST')"/>
<xsl:message select="HttpURLConnection:setRequestProperty($conn, 'Content-Type', 'application/json; utf-8')"/>
<xsl:message select="HttpURLConnection:setRequestProperty($conn, 'Accept', 'application/json')"/>
<xsl:message select="HttpURLConnection:setDoOutput($conn, true())"/>
<xsl:variable name="os" select="HttpURLConnection:getOutputStream($conn)"/>
<xsl:variable name="utf8Charset" select="Charset:forName('utf-8')"/>
<xsl:variable name="payloadJavaString" as="jt:java.lang.String" select="JString:new($payload)"/>
<xsl:variable name="byteArray" select="ByteBuffer:array(Charset:encode($utf8Charset, $payloadJavaString))"/>
<xsl:message select="OutputStream:write($os, $byteArray, 0, count($byteArray))"/>
<xsl:message select="OutputStream:close($os)"/>
<xsl:variable name="responseCode" select="HttpURLConnection:getResponseCode($conn)"/>
<xsl:variable name="br" select="BufferedReader:new(InputStreamReader:new(HttpURLConnection:getInputStream($conn), 'utf-8'))"/>
<xsl:variable name="response" select="BufferedReader:lines($br) => Stream:toArray()"/>
<result code="{$responseCode}">{$response}</result>
</xsl:template>
</xsl:stylesheet>