SAPфорум.RU
https://sapboard.ru/forum/

XSLT преобразование
https://sapboard.ru/forum/viewtopic.php?f=70&t=91408
Страница 1 из 1

Автор:  doleynikov [ Вт, сен 22 2015, 14:14 ]
Заголовок сообщения:  XSLT преобразование

Добрый день!
У меня проблема: нужно сделать xslt мапинг вот для чего: на входе XML вида:
Code:
<textLine>
   <text>тут некоторая строка текста</text>
   <format>*</format>
</textLine>
<textLine>
   <text>которая продолжается в следующих тегах</text>
   <format> </format>
</textLine>
<textLine>
   <text>а тут новый абзац текста</text>
   <format>*</format>
</textLine>
<textLine>
   <text>а тут новая строка текста</text>
   <format>/</format>
</textLine>

на выходе нужно получить текстовую строку в формате html:

Code:
<p>тут некоторая строка текста которая продолжается в следующих тегах</p>
<p>а тут новый абзац текста<br/>а тут новая строка текста</p>


Мне кажется это достаточно сложно. Можно более простой приемлемый вариант:

Code:
<p>тут некоторая строка текста которая продолжается в следующих тегах<br/> а тут новый абзац текста<br/>а тут новая строка текста</p>


то есть каждый раз, если есть формат "*" или "/" в конкатенируемую строку вставлять тег разрыва строки.

Помогите, пожалуйста.

Автор:  Chaser009 [ Ср, сен 23 2015, 04:03 ]
Заголовок сообщения:  Re: XSLT преобразование

Сам с XSLT практически не работаю. Если на коленке за пять минут:

Сообщение:
Code:
<Message>
<textLine>
   <text>тут некоторая строка текста</text>
   <format>*</format>
</textLine>
<textLine>
   <text>которая продолжается в следующих тегах</text>
   <format> </format>
</textLine>
<textLine>
   <text>а тут новый абзац текста</text>
   <format>*</format>
</textLine>
<textLine>
   <text>а тут новая строка текста</text>
   <format>/</format>
</textLine>
</Message>


Код:
Code:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/*">
   <xsl:element name="p">
   <xsl:for-each select="textLine">
      <xsl:value-of select="text"/>
      <xsl:if test="format = '*' or format='/'">
         <xsl:element name="br"/>
      </xsl:if>
   </xsl:for-each>
   </xsl:element>

</xsl:template>

</xsl:stylesheet>


Пусть гуру поправят, где что не так. :-) На тестовом примере работает.

Автор:  doleynikov [ Ср, сен 23 2015, 09:38 ]
Заголовок сообщения:  Re: XSLT преобразование

Спасибо! получается, у меня реальный случай несколько сложнее. Попробую описать (это вывод IDOC=ARTMAS05, на самом деле).
Code:
<zARTMAS>
<material>00000111111234</material>
<E1BPE1MLTXRT>
   <TEXT_LINE>тут некоторая строка текста</TEXT_LINE>
   <FORMAT_COL>*</FORMAT_COL>
</E1BPE1MLTXRT>
<E1BPE1MLTXRT>
   <TEXT_LINE>которая продолжается в следующих тегах</TEXT_LINE>
   <FORMAT_COL> </FORMAT_COL>
</E1BPE1MLTXRT>
<E1BPE1MLTXRT>
   <TEXT_LINE>а тут новый абзац текста</TEXT_LINE>
   <FORMAT_COL>*</FORMAT_COL>
</E1BPE1MLTXRT>
<E1BPE1MLTXRT>
   <TEXT_LINE>а тут новая строка текста</TEXT_LINE>
   <FORMAT_COL>/</FORMAT_COL>
</E1BPE1MLTXRT>

<E1BPE1MLTXRT>
   <TEXT_LINE>а тут новая строка текста с выравниванием по центру</TEXT_LINE>
   <FORMAT_COL>С</FORMAT_COL>
</E1BPE1MLTXRT>
<E1BPE1MLTXRT>
   <TEXT_LINE>которая продолжается тут</TEXT_LINE>
   <FORMAT_COL> </FORMAT_COL>
</E1BPE1MLTXRT>
</zARTMAS>


получается, в результате нужно получить:

Code:
<OutputDoc>
<matcode>00000111111234</matcode>
<HTMLdescription>
"<p>тут некоторая строка текста
которая продолжается в следующих тегах
</p>
<p>а тут новый абзац текста
<br/>а тут новая строка текста
</p>
<p align=center>а тут новая строка текста с выравниванием по центру
которая продолжается тут
</p>"
</HTMLdescription>
</OutputDoc>


Можно ли такое сделать?

Автор:  doleynikov [ Чт, сен 24 2015, 09:04 ]
Заголовок сообщения:  Re: XSLT преобразование

в спецификации сказано, что тег
Цитата:
<p>
закрывать не обязательно! если за ним стоят другие параграфы и он не входит в тег
Цитата:
<a>
. Тогда все проще - не нужно следить за закрытием предыдущего параграфа при начале следующего!

Автор:  Chaser009 [ Чт, сен 24 2015, 10:50 ]
Заголовок сообщения:  Re: XSLT преобразование

Исходный XML:
Code:
<Texts>
<textLine>
<text>String1</text>
<format>*</>
</textLine>
<textLine>
<text>String2</text>
<format></>
</textLine>
<textLine>
<text>String3</text>
<format>*</>
</textLine>
<textLine>
<text>String4</text>
<format>*</>
</textLine>
</Texts>


"*" - признак конца параграфа.

Code:
<xsl:template match="/*">
    <output>
        <xsl:for-each select="textLine[position()=1 or preceding-sibling::textLine[1]/format='*']">
            <p>
                <xsl:apply-templates select="."/>
            </p>
        </xsl:for-each>
    </output>
</xsl:template>

<xsl:template match="textLine">
    <xsl:value-of select="text"/>
    <xsl:variable name="next-item" select="following-sibling::textLine[1]" />
    <xsl:if test="not(format='*') and $next-item">
        <xsl:text> </xsl:text>
        <xsl:apply-templates select="$next-item"/>
    </xsl:if>
</xsl:template>


Данный темплейт разобьет на параграфы.
Остальное форматирование просто реализуется внутри темплейта.

Автор:  doleynikov [ Пн, сен 28 2015, 10:14 ]
Заголовок сообщения:  Re: XSLT преобразование

Спасибо. У меня с этим xsl не складываются отношения - мозг закостенел ;-)

Я сделал в стиле программирования на "нормальных" языках - через выбор варианта, без шаблонов.
Цитата:
<ns1:description>
<ns0:for-each select="/ARTMAS05/IDOC/E1BPE1MLTXRT" xmlns:ns0="http://www.w3.org/1999/XSL/Transform">
<ns0:variable name="E1BPE1MLTXRT" select="."/>
<ns0:if test="$E1BPE1MLTXRT/TEXT_ID = &apos;PRUE&apos;">
<ns0:choose>
<ns0:when test="./FORMAT_COL = &apos;*&apos;">
<ns0:value-of select="concat( &apos;&lt;p&gt;&apos; ,./TEXT_LINE, &apos; &apos; )" xmlns:ns0="http://www.w3.org/1999/XSL/Transform"/>
</ns0:when>
<ns0:when test="./FORMAT_COL = &apos;/&apos;">
<ns0:value-of select="concat( &apos;&lt;br/&gt;&apos;,./TEXT_LINE )" xmlns:ns0="http://www.w3.org/1999/XSL/Transform"/>
</ns0:when>
<ns0:when test="./FORMAT_COL = &apos;C&apos;">
<ns0:value-of select="concat( &apos;&lt;p ALIGN=CENTER&gt;&apos; ,./TEXT_LINE, &apos; &apos; )" xmlns:ns0="http://www.w3.org/1999/XSL/Transform"/>
</ns0:when>
<ns0:when test="./FORMAT_COL = &apos;B&apos;">
<ns0:value-of select="concat( &apos;&lt;p ALIGN=JUSTIFY&gt;&apos; ,./TEXT_LINE, &apos; &apos; )" xmlns:ns0="http://www.w3.org/1999/XSL/Transform"/>
</ns0:when>
<ns0:when test="./FORMAT_COL = &apos;L&apos;">
<ns0:value-of select="concat( &apos;&lt;p ALIGN=left&gt;&apos; ,./TEXT_LINE, &apos; &apos; )" xmlns:ns0="http://www.w3.org/1999/XSL/Transform"/>
</ns0:when>
<ns0:otherwise>
<ns0:value-of select="concat(./TEXT_LINE, &apos; &apos; )" xmlns:ns0="http://www.w3.org/1999/XSL/Transform"/>
</ns0:otherwise>
</ns0:choose>
</ns0:if>
</ns0:for-each>
</ns1:description>

Автор:  doleynikov [ Вт, сен 29 2015, 08:53 ]
Заголовок сообщения:  Re: XSLT преобразование

Продолжение вопроса.
Оказалось, что нужно не только форматирование абзацев :oops: менять, но и, возможно, САПовский гипертекст. Поискав , нашел модуль CONVERT_ITF_TO_HTML, который теоретически делает то, что мне нужно. Применять его при формировании IDOC, вероятно, не будут. Так, что придется мне.
У меня сделано xslt преобразование. как можно после xslt результат еще через один маппинг прогнать? чтобы там сделать вызов этого модуля? Обязательно городить Integration Process или можно как-то по другому выйти из положения?

Автор:  Chaser009 [ Вт, сен 29 2015, 09:11 ]
Заголовок сообщения:  Re: XSLT преобразование

Не совсем понятен вопрос. Если у Вас есть Operation mapping, где Вы xslt пользуете, что мешает туда еще один Message mapping следом добавить?

Автор:  doleynikov [ Вт, сен 29 2015, 10:09 ]
Заголовок сообщения:  Re: XSLT преобразование

Ага! Я пробовал, но просветление не пришло ;-(

У меня xslt маппинг из сообщения А в сообщение Б. вторым я создал графический маппинг из Б в Б.
При тесте получаю сообщение
Цитата:
RuntimeException when executing application mapping program com/sap/xi/tf/_arProduct_description2HTML_; Details: com.sap.aii.mappingtool.tf7.IllegalInstanceException; Cannot create target element /ns0:setProductItems. Values missing in queue context. Target XSD requires a value for this element, but the target-field mapping does not create one. Check whether the XML instance is valid for the source XSD, and whether the target-field mapping fulfils the requirement of the target XSD


Мне не приходилось раньше делать такие каскадные мапинги. Что я делаю не так?

Вот что получаю в дебаг трейсе

Цитата:
10:10:17 Start of test
Creating mapping sequence with 2 steps.
Creating step 0.
Creating step 1.
Start executing mapping sequence with 2 steps.
Executing mapping step 0

Call XSLT processor with stylsheet 20150922/ARTMAS05_2_arProducts.xsl.

Returned form XSLT processor.
XSLT transformation: 20150922/ARTMAS05_2_arProducts.xsl completed with 0 warning(s).
Mapping step 0 has been executed.
Executing mapping step 1

Message Mapping arProduct_description2HTML | http://www.ххх.ru/interfaces/istore/sap not compiled. Starting compilation...

Compilation of arProduct_description2HTML successful

Loaded class com.sap.xi.tf._arProduct_description2HTML_

Message Mapping arProduct_description2HTML | http://www.ххх.ru/interfaces/istore/sap not compiled. Starting compilation...

Compilation of arProduct_description2HTML successful

Loaded class com.sap.xi.tf._arProduct_description2HTML_$MT$InnerLibsList

Message Mapping arProduct_description2HTML | http://www.ххх.ru/interfaces/istore/sap not compiled. Starting compilation...

Compilation of arProduct_description2HTML successful

Loaded class com.sap.xi.tf._arProduct_description2HTML_$MT$InnerParamsList

Call method execute of the application Java mapping com.sap.xi.tf._arProduct_description2HTML_

*** START APPLICATION TRACE ***
Document start

*** END APPLICATION TRACE ***

RuntimeException during appliction Java mapping com/sap/xi/tf/_arProduct_description2HTML_

com.sap.aii.mappingtool.tf7.IllegalInstanceException: Cannot create target element /ns0:setProductItems. Values missing in queue context. Target XSD requires a value for this element, but the target-field mapping does not create one. Check whether the XML instance is valid for the source XSD, and whether the target-field mapping fulfils the requirement of the target XSD at com.sap.aii.mappingtool.tf7.AMappingProgram.processNode(AMappingProgram.java:375) at com.sap.aii.mappingtool.tf7.AMappingProgram.start(AMappingProgram.java:512) at com.sap.aii.mappingtool.tf7.Transformer.start(Transformer.java:142) at com.sap.aii.mappingtool.tf7.AMappingProgram.transform(AMappingProgram.java:644) at com.sap.aii.ib.server.mapping.execution.JavaMapping.executeStep(JavaMapping.java:92) at com.sap.aii.ib.server.mapping.execution.Mapping.execute(Mapping.java:60) at com.sap.aii.ib.server.mapping.execution.SequenceMapping.executeStep(SequenceMapping.java:40) at com.sap.aii.ib.server.mapping.execution.Mapping.execute(Mapping.java:60) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:87) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:54) at com.sap.aii.ibrep.server.mapping.rt.MappingHandlerAdapter.run(MappingHandlerAdapter.java:139) at com.sap.aii.ibrep.server.mapping.exec.ExecuteIfMapCommand.execute(ExecuteIfMapCommand.java:33) at com.sap.aii.ib.server.mapping.exec.CommandManager.execute(CommandManager.java:43) at com.sap.aii.ibrep.server.mapping.ServerMapService.execute(ServerMapService.java:40) at com.sap.aii.ibrep.server.mapping.MapServiceBean.execute(MapServiceBean.java:40) at sun.reflect.GeneratedMethodAccessor1592.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:592) at com.sap.engine.services.ejb3.runtime.impl.RequestInvocationContext.proceedFinal(RequestInvocationContext.java:43) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:166) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatesTransition.invoke(Interceptors_StatesTransition.java:19) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Resource.invoke(Interceptors_Resource.java:74) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.doWorkWithAttribute(Interceptors_Transaction.java:38) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.invoke(Interceptors_Transaction.java:22) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:191) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatelessInstanceGetter.invoke(Interceptors_StatelessInstanceGetter.java:23) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_SecurityCheck.invoke(Interceptors_SecurityCheck.java:21) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_ExceptionTracer.invoke(Interceptors_ExceptionTracer.java:16) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.DefaultInvocationChainsManager.startChain(DefaultInvocationChainsManager.java:133) at com.sap.engine.services.ejb3.runtime.impl.DefaultEJBProxyInvocationHandler.invoke(DefaultEJBProxyInvocationHandler.java:164) at com.sun.proxy.$Proxy1013.execute(Unknown Source) at sun.reflect.GeneratedMethodAccessor1591.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:592) at com.sap.engine.services.rmi_p4.P4DynamicSkeleton.dispatch(P4DynamicSkeleton.java:234) at com.sap.engine.services.rmi_p4.DispatchImpl._runInternal(DispatchImpl.java:358) at com.sap.engine.services.rmi_p4.server.ServerDispatchImpl.run(ServerDispatchImpl.java:70) at com.sap.engine.services.rmi_p4.P4Message.process(P4Message.java:62) at com.sap.engine.services.rmi_p4.P4Message.execute(P4Message.java:37) at com.sap.engine.services.cross.fca.FCAConnectorImpl.executeRequest(FCAConnectorImpl.java:900) at com.sap.engine.services.rmi_p4.P4Message.process(P4Message.java:53) at com.sap.engine.services.cross.fca.MessageReader.run(MessageReader.java:58) at com.sap.engine.core.thread.execution.Executable.run(Executable.java:108) at com.sap.engine.core.thread.execution.CentralExecutor$SingleThread.run(CentralExecutor.java:304)
10:10:20 End of test


Если запускаю только первый шаг - он проходит успешно и создает всю нужную структуру
Code:
<?xml version="1.0" encoding="UTF-8"?><ns1:setProductItems xmlns:ns1="http://www.ххх.ru:443/"><ns1:arProduct><ns1:arProductEl><ns1:code>000000000001000570</ns1:code><ns1:name>Шляпа Шампания текстиль с узкими полями блестящая крошка в ассортименте Н87468 </ns1:name><ns1:short_name>@ OVO Discovery Блинница антип покр220м1</ns1:short_name><ns1:active_from>20100304</ns1:active_from><ns1:active_to>99991231</ns1:active_to><ns1:section>17010203V</ns1:section><ns1:sort>100</ns1:sort><ns1:price_band>01</ns1:price_band><ns1:brand>SKOVO</ns1:brand><ns1:attr_new/><ns1:article>РАПФВЫОЛ</ns1:article><ns1:announce>Блинница SCOVO Discovery СД-039 антипригарное покрытие алюминий 22см  </ns1:announce><ns1:description>&lt;p&gt;Просто текст длинный, который не уместился в строку страницы просто текст длинный, который не уместился в строку страницы &lt;p&gt;Новая строка  с форматом по умолчанию &lt;p ALIGN=JUSTIFY&gt;В просто длинный текст с выравниванием по ширине. Это не заметно если строка меньше ширины экрана &lt;p ALIGN=CENTER&gt;С С выравниванием по центру &lt;p&gt;&lt;B&gt;Выделено&lt;/&gt; &lt;p ALIGN=left&gt;L с выравниванием по левому краю &lt;p ALIGN=left&gt;&lt;U&gt;U Подчеркнуто&lt;/&gt; &lt;br/&gt;Обычный текст - после разрыва строки /&lt;p ALIGN=JUSTIFY&gt;В просто длинный текст с выравниванием по ширине. Это не заметно если строка меньше ширины экрана Вот тут начинается продолжение вывода с форматированием по ширине. Вот такой вот пример . </ns1:description><ns1:props><ns1:ArrayOfPropEl><ns1:name>COLOR</ns1:name><ns1:value>Красный</ns1:value></ns1:ArrayOfPropEl><ns1:ArrayOfPropEl><ns1:name>GENDER</ns1:name><ns1:value>мужчина</ns1:value></ns1:ArrayOfPropEl><ns1:ArrayOfPropEl><ns1:name>PICTURE_DESIGN</ns1:name><ns1:value>Полосы</ns1:value></ns1:ArrayOfPropEl><ns1:ArrayOfPropEl><ns1:name>PACKAGE_TYPE</ns1:name><ns1:value>Чемодан</ns1:value></ns1:ArrayOfPropEl></ns1:props><ns1:measures><ns1:ArrayOfMeasureEl><ns1:primary>-1</ns1:primary><ns1:numerator>25</ns1:numerator><ns1:denumerator>1</ns1:denumerator><ns1:title>M</ns1:title><ns1:titleIso>MTR</ns1:titleIso><ns1:height>0.000</ns1:height><ns1:length>0.000</ns1:length><ns1:volume>0.000</ns1:volume><ns1:weight>0.000</ns1:weight><ns1:width>0.000</ns1:width></ns1:ArrayOfMeasureEl><ns1:ArrayOfMeasureEl><ns1:primary>1</ns1:primary><ns1:numerator>1</ns1:numerator><ns1:denumerator>1</ns1:denumerator><ns1:title>ST</ns1:title><ns1:titleIso>PCE</ns1:titleIso><ns1:height>0.000</ns1:height><ns1:length>0.000</ns1:length><ns1:volume>0.017</ns1:volume><ns1:weight>3.817</ns1:weight><ns1:width>0.000</ns1:width></ns1:ArrayOfMeasureEl><ns1:ArrayOfMeasureEl><ns1:primary>-1</ns1:primary><ns1:numerator>1</ns1:numerator><ns1:denumerator>1</ns1:denumerator><ns1:title>ZVN</ns1:title><ns1:titleIso>ZVN</ns1:titleIso><ns1:height>0.000</ns1:height><ns1:length>0.000</ns1:length><ns1:volume>0.017</ns1:volume><ns1:weight>3.900</ns1:weight><ns1:width>0.000</ns1:width></ns1:ArrayOfMeasureEl><ns1:ArrayOfMeasureEl><ns1:primary>-1</ns1:primary><ns1:numerator>12</ns1:numerator><ns1:denumerator>1</ns1:denumerator><ns1:title>ZVS</ns1:title><ns1:titleIso>ZVS</ns1:titleIso><ns1:height>0.000</ns1:height><ns1:length>0.000</ns1:length><ns1:volume>0.017</ns1:volume><ns1:weight>4.800</ns1:weight><ns1:width>0.000</ns1:width></ns1:ArrayOfMeasureEl></ns1:measures><ns1:barcodes><ns1:ArrayOfBarcodeEl><ns1:primary>-1</ns1:primary><ns1:barcode>4607028555619</ns1:barcode></ns1:ArrayOfBarcodeEl><ns1:ArrayOfBarcodeEl><ns1:primary>1</ns1:primary><ns1:barcode>4607153314310</ns1:barcode></ns1:ArrayOfBarcodeEl></ns1:barcodes></ns1:arProductEl></ns1:arProduct></ns1:setProductItems>

Автор:  Chaser009 [ Вт, сен 29 2015, 10:20 ]
Заголовок сообщения:  Re: XSLT преобразование  Тема решена

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

Как проверить? Оставьте только первый мэппинг, прогоните, скопируйте результирующий xml
Потом результат подкиньте в свой второй мэппинг, там увидите, если проблема со структурой сообщения входного, то сегменты красные будут

Автор:  doleynikov [ Вт, сен 29 2015, 10:31 ]
Заголовок сообщения:  Re: XSLT преобразование

Да, похоже на неймспейсы, которые подставляются в XSLT. Спасибо за наводку и объяснения. Иду разбираться. Если что - еще спрошу ;-)

PS: Это они, родимые, и есть!!! заменил - прошел второй шаг!

Автор:  Chaser009 [ Вт, сен 29 2015, 10:47 ]
Заголовок сообщения:  Re: XSLT преобразование

Ну вот и чудненько :-)

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/