Feeding output of

into of HTTP PUT request

2019-08-09 15:25发布

My goal for my Xproc pipeline below is to take in a source XML document, run 2 XSLT transforms with <p:xslt> steps, then feed the output XML after the 2nd <p:xslt> to the <c:body> of the <p:http-request> step:

<p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
    xmlns:c="http://www.w3.org/ns/xproc-step"
    version="1.0">

  <p:input port="source" primary="true"/>
  <p:output port="result" primary="true"/>

  <p:serialization port="result" 
                   indent="false" 
                   method="xml" 
                   encoding="utf-8" 
                   omit-xml-declaration="false"
                   doctype-system="myDTD.dtd" 
                   doctype-public="-//DOCTYPE-HERE"/>

  <p:xslt>
    <p:input port="stylesheet">
      <p:document href="XSLT-1.xslt"/>
    </p:input>
  </p:xslt>

  <p:xslt>
    <p:input port="stylesheet">
      <p:document href="XSLT-2.xslt"/>
    </p:input>
  </p:xslt>

  <p:http-request omit-xml-declaration="false" 
                  encoding="UTF-8">
    <p:input port="source">
      <p:inline>
        <c:request href="http://localhost:80/myRESTserver/dburi/myDOC.xml" 
                   auth-method="basic" 
                   username="user" 
                   password="admin" 
                   method="put">
          <c:body content-type="text/xml" >

          </c:body>
        </c:request>
      </p:inline>
    </p:input>
  </p:http-request>

Is there a way to achieve this? When I try executing this code as is, the <p:http-request> is invoked first (PUTS an empty XML file into the database).

1条回答
不美不萌又怎样
2楼-- · 2019-08-09 16:06

The reason why p:http-request runs first is that it does not depend on any other steps in the pipeline. The source input port of p:http-request is bound to a static inline c:request document and therefore the step does not need to wait for any other steps to finish first. The step can therefore run at any time.

To fix that, you need to connect the input port of p:http-request to the second p:xslt step. This can be done explicitly (using p:pipe) or implicitly (relying on the fact that the XProc processor will manufacture implied p:pipe connections automatically). Let's demonstrate both while solving your main question (embedding the output of p:xslt in c:body) in the process:

For embedding XML content in XML wrappers, the usual go-to XProc steps are p:wrap and p:wrap-sequence. However, they work with simple (one level) XML wrapper elements, so they are not all that helpful if you want to wrap in multiple levels of XML (as in your case: c:request/c:body). So you have to use something else - for example the p:insert step:

...
<p:xslt name="xslt2">
  <p:input port="stylesheet">
    <p:document href="XSLT-2.xslt"/>
  </p:input>
</p:xslt>
<p:insert match="c:request/c:body" position="first-child">
  <p:input port="source">
    <p:inline>
      <c:request href="http://localhost:80/myRESTserver/dburi/myDOC.xml" 
                 auth-method="basic" 
                 username="user" 
                 password="admin" 
                 method="put">
        <c:body content-type="text/xml">
        </c:body>
      </c:request>
    </p:inline>
  </p:input>
  <p:input port="insertion">
    <p:pipe step="xslt2" port="result"/>
  </p:input>
</p:insert>
<p:http-request omit-xml-declaration="false"
                encoding="UTF-8"/>
...

Let's take a look at what this does:

  1. We gave the second p:xslt step a name (xslt2).
  2. We placed an p:identity step in between the second p:xslt step and the p:http-request step. The p:identity step uses a static c:request/c:body document as the insertion target and the output of the step named xslt2 as the content to be inserted. It inserts the content as the first child of c:request/c:body.
  3. We removed the static connection from the source input port of the p:http-request. This is fine because the output of the p:insert step will flow into the source input port of p:http-request automatically.
查看更多
登录 后发表回答