XML über TextHTML Writer mit Rows aus mehreren Datastores

Hallo liebes Synesty Team,


wir bauen zurzeit eine XML über den TextHTMLWriter. Dafür benötigen wir aber Werte aus mehreren Datastores. Dafür möchte ich die Werte über "getRows() as row" einbinden. Meine Frage ist bestimmt recht simpel, bloß ist mir die Syntax nicht ganz klar, wenn man Rows aus mehreren Datastores verwendet und ich habe schon einiges rumprobiert.

Ausschnitt aus meinem Ansatz:
<?xml version="1.0" encoding="utf-8"?>

<#list XXXXXX.getRows() as row> (erster Datastore)
INHALT --> hier verwende ich dann ${row.get("ROW aus dem ersten Datastore")!}
</#list>


<#list XXXXXX.getRows() as row> (zweiter Datastore)
INHALT --> hier verwende ich dann ${row.get("ROW aus dem zweiten Datastore")!}
</#list>


Das Ergebnis:
Wenn ich das so mache, wird mir die gesamte XML nach der Schließung meiner ersten </#list> erneut ausgegeben.


Kann mir jemand bitte kurz helfen, wie der XML-Aufbau richtig wäre, wenn ich die Rows aus mehreren Datastores aufgreifen möchte?

Hallo,


es müssten so in etwa wie im Beispiel aussehen:



<XMLTag>
<#list spreadsheet@SearchMasterDatastore_1.getRows() as row> 
  ${row.get("spaltenname")!}
</#list>

<#list spreadsheet@SearchMasterDatastore_2.getRows() as row> 
  ${row.get("spaltenname")!}
</#list>
</XMLTag>



Die umschließenden XML Tags müssten dann vor und nach den Freemarker-Blöcken gesetzt werden.

Die inneren XML Tags müssten für jeden Datastore innerhalb jedes <#list></#list> Blockes gleich für die entsprechenden Spalten geschrieben werden.



${row.get("spaltenname")!} greift auf die Spalte der durchlaufenden Zeilen zu. Damit sollte sich die XML erfolgreich erstellen lassen.


EIn anderer weg wäre alle SearchDatastore Steps mit einem mit einem SpreadsheedAppend zu einem Spreadsheet zusammenzufügen und im TextHTMLWriter nur auf das eine Spreadsheet zuzugreifen.



Viele Grüße,


Rocco

Versuch mal in den zwei "list" Loops die "row" Objekt unterschiedlich zu benennen, z.B. row2:

<xml>
<#list spreadsheet@SearchMasterDatastore_1.getRows() as row1> 
  <element>${row1.get("spaltenname")!}</element>
</#list>

<#list spreadsheet@SearchMasterDatastore_2.getRows() as row2> 
  <element>${row2.get("spaltenname")!}</element>
</#list>
</xml>

Evtl. ist auch der Ouput von SearchMasterDatastore2 leer, in diesem Fall vermute ich hätte row immer noch die Daten aus der ersten Loop.

Verschiedene Loop-Variablen sind nicht nötig da sie nur Innerhalb der Schleife Gültigkeit haben.

Vielen Dank für die fixe Hilfe. Zwar komme ich mit dem Schritt etwas weiter, bloß tauchen nun andere Probleme bei den Schleifen auf. Ich bitte um erneute Hilfe und fang gerne von Null an:

Ziel: XML für jede Order erstellen
(Ich habe bereits den Eintrag gefunden, leider bringt er mir nicht weiter https://support.synesty.com/support/solutions/articles/11000027102-wie-erstelle-ich-eine-einzelne-xml-datei-oder-mehrere-xml-dateien-aus-einem-spreadsheet- )

Flow:

  1. ShopwareSearchOrders
  2. AuftragskopfFilter
  3. AuftragspositionenFilter
  4. Auftragsdaten DatastoreWriter
  5. Auftragspositionen Datastore Writer

    Dann folgt diese Vorbereitung, bei der ich unsicher bin:

    image

    Hier hatte ich zuerst 2x Search Datastore eingebunden, um die Daten aus dem Orderhead und Positionen zu verwenden, dann habe ich es ebenfalls mit einem einzigen SearchDatastore, der ebenfalls Varianten ausgibt, versucht. Leider komme ich noch immer nicht zum gewünschten Ergebnis der XML, da bei ${row.get("name")!}] immer alle Rows ausgegeben werden (unnötig bei z.B. Rechnungsbetrag oder Datum) und ich solch eine mehrfache Ausgabe natürlich nur ausgewählten Feldern wie Artikelnummer oder Artikelpreis wünsche (falls mehrere Artikel bestellt wurden).


Hier die groben Elemente der XML (der Aufbau ist von unserem System vorgegeben, es geht rein um das richtige Output):

Im Head sollen je Ordernumber einmalig z.B. ausgegeben werden:

  • DocumentID
  • CreationDate
  • Ordernumber
  • etc.

Artikel Positionen, sollen je nach Ordernumber mehrfach ausgespielt werden:
  • Position (Positionsanzahl der Bestellung, kann ich hier automatisch irgendwie hochzählen?)
  • Artikelmenge
  • Preis
  • etc.

Fragen:

  • Scheinbar komme ich mit den Loops nicht richtig klar. Ich glaube ich stehe einfach auf dem Schlauch und sehe das offensichtliche Problem nicht. Ich habe es mit dem obrigen Beispiel probiert und den Datastore Artikelauftragsdaten und Artikelpositionen getrennt angegeben, aber es werden trotzdem Loops ausgegeben, dort wo ich es nicht möchte. Mit dem SeachDatastore-Versuch 2 (search for Parents& show variants) habe ich den zweiten Versuch gestartet, dennoch werden hier logischerweise auch alle Rows ausgegeben.
  • Wie und wo kann ich denn sagen "Erstelle eine XML jeder Ordernumber und füge nur die Positionen variabel ein (mit Hochzählen der Position)"? Falls es bereits andere Diskussionen zu dem Thema gibt, wäre ich dafür auch sehr dankbar.

Probieren Sie mal diese Vorlage Hierarchische XML oder JSON Datei aus Spreadsheet erzeugen (komplexeres Beispiel). Die hat genau ein solches Beispiel mit Auftragspositionen.


Die Grundstruktur ist ungefähr so:


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

<#list spreadsheet@SearchMasterDatastore_1.getRows() as row> 

<#if (row.children()?? && row.children()?size > 0) >
        <Name>${row.get("shipping_address_given_name")!} ${row.get("shipping_address_family_name")!}</Name>  
        <Street>${row.get("shipping_address_address1")!}</Street>  
        <City>${row.get("shipping_address_city")!}</City>  
        <Zip>${row.get("shipping_address_zip")!}</Zip>  
        <Country>${row.get("shipping_address_country")!}</Country>  
    <Items>

    <#list row.children() as ch>

       <Item PartNumber="${ch['line_items_sku']!}">
          <ProductName><![CDATA[${ch['line_items_title']!}]]></ProductName>
          <Quantity>${ch['line_items_quantity']!}</Quantity>
          <Price>${ch['line_items_price']!}</Price>
          <Currency>${row.get("currency")!}</Currency>
       </Item>
   </#list>

    </Items>
 </PurchaseOrder>
</#if>

</#list>
</PurchaseOrders> 



Wichtig ist:

  • nur ein einziger SearchDatastore mit showChildren=false (das ist wichtig: Aus dem SearchDatastore dürfen nur die Auftragskopfdaten rauskommen. Auf die Auftragspositionen kann man trotzdem zugreifen per zweiter Schleife row.children()) Das klingt zwar etwas unlogisch, liegt aber daran, dass man hier Spreadsheet und Freemarker Script kombiniert. Im Spreadsheet (das was man in der Vorschau sieht), darf nur die Kopfzeile rauskommen. Per Skript kommt man dann aber auch an die Children-Zeilen, um diese auszugeben).
  • dies unter der Annahme, dass die Datastore als Master-Child Datastores verknüft sind



Vielen, vielen Dank für die Hilfe!

Ich bitte erneut, um Unterstützung. Ich stehe vor dem nächsten Problem: Ich möchte die Summe aller Artikelpreise je Order berechnen und diese in der XML ausgeben. Die Artikelpreise stehen in meiner <#list row.children() as ch>. Dieses Element darf aber demnach nicht im Loop stehen, sondern soll in einem einzelnen XML-Element wie

<InvoiceAmount>"Summe Artikelpreise je Order aus Child Datastore" </InvoiceAmount>

ausgegeben werden.

Ich bin da echt überfragt. Alternativ zu dieser direkten Lösung in der XML könnte ich natürlich versuchen, die Summe im Child-Datastore in einer Spalte zu berechnen und diese dann in den Parent-Datastore zu schreiben.


Gibt es zu eines der beiden Möglichkleiten schon einen Thread? Ich freue mich über jede Hilfe!





Ja, diese aggregierten Werte über Children ist schon recht komplex. Es gibt sicher mehrere Wege.

Einer davon wäre innerhalb des Freemarker-Scripts mit Hilfsvariablen zu arbeiten. Hier mal ein Beispiel des invoiceAmount auf Order-Ebene (siehe <#assign>).
Die Idee ist: Man muss hier quasi mehrfach über die children iterieren. Ja das kostet etwas performance, sollte sich aber in Grenzen halten, wenn man nicht tausende Items pro Order hat.



<#list spreadsheet@SearchMasterDatastore_1.getRows() as row> 

<#assign invoiceAmount = 0 />

<#if (row.children()?? && row.children()?size > 0) >

  <#list row.children() as ch>
    <#assign invoiceAmount += ch.get("itemAmount")?number />
  </#list>

  <InvoiceAmount>${invoiceAmount}</InvoiceAmount>
  

  <#list row.children() as ch>
    ... und hier jetzt alle xml-tags der Children, wie sie vorher auch schon da waren.
  </#list>
  



</#if>

</#list>