希望使用来自 Saxon 的 Java 或 .NET 调用从 XSLT 执行 HTTP POST

问题描述 投票:0回答:1

我使用一种专有工具,通过 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 .net xslt saxon
1个回答
0
投票

我摸索出了一些自反 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>
© www.soinside.com 2019 - 2024. All rights reserved.