我想用 XSLT 3.0 and its json-to-xml() function 进行实验(在 Delphi 代码中) :
In XSLT 3.0, an inbound document can be in JSON, rather than XML. The processor can take that document, use the json-to-xml() function to convert it into a specific known XML format, process that through the templates, then convert the resulting output back into JSON (or can convert it into HTML 5 among other formats
但我被困在两个地方:
如何使用 JSON 字符串作为转换源?尝试将其加载到
TXMLDocument
中会出现(当然?)“格式错误”错误然后我将如何应用“
json-to-xml()
函数”。我找到的有关在 Delphi 中使用 XSLT 转换的所有示例都使用 TransformNode 函数,如下代码所示。 像lDoc.Node.json-to-xml
这样的东西不会编译。
.
var
lDoc, lXSL, lRes: IXMLDocument;
lUTF8Str : UTF8String;
begin
lDoc := LoadXMLData(AXMLString);
lXSL := LoadXMLData(cRemoveNSTransform);
lRes := NewXMLDocument;
lDoc.Node.TransformNode(lXSL.Node,lRes); // Param types IXMLNode, IXMLDocument
lRes.SaveToXML(lUTF8Str);
有人能指出我正确的方向吗?
最佳答案
我将为我自己的问题编写一个“指南”,该指南不使用 XSLT,而是使用 IP*Works! Delphi components我们已经订阅了。
这至少可以为其他人提供一个可用的选项,或者大致了解如何“推出自己的”。
我们使用IP*Works! TipwJSON和 TipwXML成分。 技巧是拦截JSON组件的解析,然后将检测到的数据写入XML组件。 这是来自测试应用程序的代码,显示了我们是如何做到的(我已经留下了日志记录代码):
TJSONTOXML = class(TIpwJSON)
private
FXML : TipwXML;
FLogLevel : Integer;
procedure ShowLogLine(AMsg: String);
procedure InterceptJSONStartElement(Sender: TObject; const Element: string);
procedure InterceptJSONEndElement(Sender: TObject; const Element: string);
procedure InterceptCharacters(Sender: TObject; const Text: string);
function GetXML: String;
public
property XML: String read GetXML;
constructor Create(AOwner: TForm; ALogLevel: Integer); overload; // For now testing on a Form
end;
constructor TJSONTOXML.Create(AOwner: TForm; ALogLevel: Integer);
begin
inherited Create(AOwner);
FLogLevel := ALogLevel;
Self.BuildDOM := false;
Self.OnStartElement := InterceptJSONStartElement;
Self.OnEndElement := InterceptJSONEndElement;
Self.OnCharacters := InterceptCharacters;
FXML := TipwXML.Create(nil);
end;
procedure TJSONTOXML.InterceptJSONEndElement(Sender: TObject; const Element: string);
begin
if Element = '' then // End of array
begin
if FLogLevel > 2 then ShowLogLine('JSON parse EndElement - Array');
FXML.EndElement;
end
else
begin
if FLogLevel > 2 then ShowLogLine('JSON parse EndElement - Element: ' + Element);
FXML.EndElement;
end;
end;
procedure TJSONTOXML.InterceptJSONStartElement(Sender: TObject; const Element: string);
begin
if Element = '' then // Start of array
begin
if FLogLevel > 2 then ShowLogLine('JSON parse StartElement - Array');
FXML.StartElement('ARRAY','');
end
else
begin
if FLogLevel > 2 then ShowLogLine('JSON parse StartElement - Element: ' + Element);
FXML.StartElement(Uppercase(Element),'');
end;
end;
procedure TJSONTOXML.ShowLogLine(AMsg: String);
// Use WM_COPYDATA to send log info to form
var CopyDataStruct: TCopyDataStruct;
begin
CopyDataStruct.dwData := 0;
CopyDataStruct.cbData := 2 + 2 * Length(AMsg);
CopyDataStruct.lpData := PChar(AMsg);
SendMessage((Owner as TForm).Handle, WM_COPYDATA, (Owner as TForm).Handle, lParam(@CopyDataStruct));
end;
function TJSONTOXML.GetXML: String;
begin
FXML.EndElement;
Result := FXML.OutputData;
end;
procedure TJSONTOXML.InterceptCharacters(Sender: TObject; const Text: string);
var lText: String;
begin
// Always surrounded by quotes, remove:
lText := StripQuotes(Text);
if FLogLevel > 2 then ShowLogLine('JSON parse characters: ' + lText);
FXML.PutString(lText);
end;
有了这个你就可以
lJSONToXML := TJSONTOXML.Create(Self,FDataLogLvl);
// Get your JSON data from somewhere, e.g. a HTTP component. Then:
lJSONToXML.Inputdata := lData;
lJSONToXML.Parse; // The Parse method initiates the parsing that was postponed by setting BuildDom := false
// The XML is now in the OutputData property of the TipwXML and can e.g. be retrieved by our:
lOutputData := lJSONToXML.XML;
请注意:
- XML 中没有命名空间信息
- JSON 数组在转换为 XML 时会转换为名为 ARRAY 的节点
- 所有数据都保存在内存中
关于使用 XSLT 3.0 的 JSON 到 XML - 如何加载 JSON 源并调用 json-to-xml 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55763865/