Как преобразовать XML с помощью XSLT? - PullRequest
0 голосов
/ 03 января 2019

У меня есть файл XML и XSLT, и я хочу использовать XSLT для преобразования XML в строку HTML, которая может быть загружена в TWebBrowser.

. Для своих тестов я использую эти файлы примеров.

XML-файл:

<?xml version="1.0" encoding="UTF-8"?>
<breakfast_menu>

<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<description>Two of our famous Belgian Waffles with plenty of real maple syrup</description>
<calories>650</calories>
</food>

<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<description>Light Belgian waffles covered with strawberries and whipped cream</description>
<calories>900</calories>
</food>

<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
<calories>900</calories>
</food>

<food>
<name>French Toast</name>
<price>$4.50</price>
<description>Thick slices made from our homemade sourdough bread</description>
<calories>600</calories>
</food>

<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
<calories>950</calories>
</food>

</breakfast_menu>

XSLT-файл:

<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
<xsl:for-each select="breakfast_menu/food">
  <div style="background-color:teal;color:white;padding:4px">
    <span style="font-weight:bold"><xsl:value-of select="name"/> - </span>
    <xsl:value-of select="price"/>
    </div>
  <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
    <p>
    <xsl:value-of select="description"/>
    <span style="font-style:italic"> (<xsl:value-of select="calories"/> calories per serving)</span>
    </p>
  </div>
</xsl:for-each>
</body>
</html>

Попытка 1:

Я нашел это решение и попробовал функцию:

Uses
  XMLDoc, XMLIntf;

function Transform(XMLContent : string; XSLContent : string) : WideString;
var
  XML : IXMLDocument;
  XSL : IXMLDocument;
begin

  XML := LoadXMLData(XMLContent);
  XSL := LoadXMLData(XSLContent);

  XML.DocumentElement.TransformNode(XSL.DocumentElement, Result)

end;

Но это выдаетнеожиданный результат:

бельгийские вафли $ 5,95Два наших знаменитых бельгийских вафли с большим количеством настоящего кленового сиропаАссорти из свежих ягод и взбитых сливок900Френч-тост. $ 4.50Толщенные ломтики, приготовленные из нашего домашнего заквасочного хлеба600. Домашний завтрак. $ 6.95Два яйца, бекон или колбаса, тосты и наш всегда популярный картофельный оладь950


Попытка 2:

Я нашел следующую функцию в разделе «Использование MSXML Parser / Transform Engine» этой страницы (Примечание: это пример Delphi 5, но я использую Delphi2007).

function DoTransform(const xml, xsl : string ): string;
var
  XMLDoc : IXMLDOMDocument;
  XSLDoc : IXMLDOMDocument;
  Template : IXSLTemplate;
  Processor : IXSLProcessor;
begin
  Result := '';
  try
    XMLDoc := CoFreeThreadedDOMDocument30.Create;
    XSLDoc := CoFreeThreadedDOMDocument30.Create;
    XMLDoc.load(xml);
    XSLDoc.load(xsl);
    Template := CoXSLTemplate30.Create;
    Template.stylesheet := XSLDoc;
    Processor := Template.createProcessor;
    Processor.input := XMLDoc;
    Processor.transform;
    result :=  Processor.output;
  finally
    XMLDoc := nil;
    XSLDoc := nil;
  end;
end;

Я импортировал библиотеку типов Microsoft XML ...

Компонент -> Импорт компонента -> Импорт библиотеки типов -> Далее -> MicrosoftXML, v6.0

... и добавлено MSXML2_TLB к предложению использования, но затем возникают некоторые другие ошибки:

E2003 Необъявленный идентификатор: 'CoFreeThreadedDOMDocument30'

E2003 Необъявленный идентификатор: 'CoXSLTemplate30'

Я переключил CoFreeThreadedDOMDocument30 на CoFreeThreadedDOMDocument60 и CoXSLTemplate30 на CoXSLTemplate60 и теперь он компилируется без ошибок.

Во время выполнения в этой строке:

Template.stylesheet := XSLDoc;

Возникает следующее исключение (на итальянском языке):

Il foglio di stile non includeдокументация.В любом случае, в формате XML в формате corretto.

На английском языке это должно выглядеть примерно так:

Таблица стилей не включаетэлемент документа.Таблица стилей пуста или это может быть неверно отформатированный документ XML.

Я протестировал другие файлы примеров, и ошибка всегда одинакова, и я не понимаю, в чем может быть проблема.

Я на правильном пути или есть лучшие способы сделать то, что мне нужно?

1 Ответ

0 голосов
/ 04 января 2019

У меня есть следующий код, который работает.Предполагается, что файл содержит XSLT, но его легко изменить.

Он был написан давно, и я спешил.Так что может быть место для некоторых улучшений.Надеюсь, это поможет.

uses
  Windows, ComObj, XMLDoc, msxmldom, msxml;

function DOMToMSDom(const Doc: IDOMDocument): IXMLDOMDocument3;
begin
  Result := ((Doc as IXMLDOMNodeRef).GetXMLDOMNode as IXMLDOMDocument3);
end;

function TransformXMLDocWithXSLTFile(const Doc: XMLIntf.IXMLDocument; const StyleSheetLocation: string; var TransformedData, Error: string): Boolean;
var
  MsxmlDoc: IXMLDOMDocument3;
  xslStyle : IXMLDOMDocument;
begin
  Result := False;
  if not FileExists(StyleSheetLocation) then 
  begin
    Error := 'Specified XSLT stylesheet file does not exist: ' + StyleSheetLocation;
    Exit;
  end;
  try
    MsxmlDoc := DOMToMSDom(Doc.DOMDocument);
    xslStyle := CoDOMDocument60.Create;
    xslStyle.load(StyleSheetLocation);
    IXMLDOMDocument3(xslStyle).setProperty('AllowXsltScript', True);
    TransformedData := MsxmlDoc.transformNode(xslStyle);
    Result := True;
  except
    on E: Exception do 
    begin
      Error := E.Message;
    end;
  end;
end;
...