2015-04-07 3 views
0

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

Моего XML

<?xml version="1.0" encoding="UTF-8"?> 
<exchange> 
<vco> 
<vco.srs> 
<vco_crsc.vco.srs>BUUBMS</vco_crsc.vco.srs> 
<vco_prgc.vco.srs>BUBSBAT02</vco_prgc.vco.srs> 
<vco_rouc.vco.srs>USMANG</vco_rouc.vco.srs> 
<cbo> 
<cbo.srs> 
<cbo_occl.cbo.srs>AJ</cbo_occl.cbo.srs> 
</cbo.srs> 
<cbo.srs> 
<cbo_occl.cbo.srs>FJ</cbo_occl.cbo.srs> 
</cbo.srs> 
</cbo> 
</vco.srs> 
</vco> 
</exchange> 

От чтения другого аналогичного поста я создал шаблон на основе битого кода. Шаблон функционирует, но в идеале я бы хотел, чтобы он отформатировался по-разному, поскольку я теряю форматирование полей из-за шаблонов. Предположим, мне нужен другой шаблон, но, как я уже сказал, не совсем уверен, что я делаю!

<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output indent="yes" method="xml"/> 
<xsl:template match="/root"> 
<ImportTask> 
<xsl:apply-templates select="CourseDetails"/>-<xsl:apply-templates select="CourseOcc"/> 
</ImportTask>  
</xsl:template> 

<xsl:template match="CourseDetails"> 
<Courses> 
<xsl:for-each select="exchange/vco/vco.srs"> 
<Course> 
<CourseCode><xsl:value-of select="vco_crsc.vco.srs"/></CourseCode>-<Programmecode><xsl:value-of select="vco_prgc.vco.srs"/></Programmecode>-<Routecode><xsl:value-of select="vco_rouc.vco.srs"/></Routecode> 
</Course> 
</xsl:for-each> 
</Courses> 
</xsl:template> 
<xsl:template match="CourseOcc"> 
<Occurences> 
<xsl:for-each select="exchange/cbo/cbo.srs"> 
<Occur> 
<OccurCode><xsl:value-of select="cbo_occl.cbo.srs"/></OccurCode> 
</Occur> 
</xsl:for-each> 
</Occurences> 
</xsl:template> 
</xsl:stylesheet> 

Это выводит:

BUUBMS 
BUBSBAT02 
USMANG 


AJ 


FJ 

который все очень хорошо, но не то, что я хочу. В идеале я хотел бы выход быть:

<ImportTask> 
    <Courses> 
    <Course>BUUBMS-BUBSBAT02-USMANG-AJ</Course> 
    <Course>BUUBMS-BUBSBAT02-USMANG-FJ<Course> 
    </Courses> 
    </ImportTask> 

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

Может кто-нибудь указать мне в правильном направлении или сказать мне, есть ли лучший способ?

Большое спасибо

ответ

0

следующие переводы XSLT ваш вход в желаемый результат. Там используются только два шаблона, один для корневого элемента, один для <cbo_occl.cbo.srs>. Последний выбирает текстовые узлы элементов, начиная с «vco_» перед этим элементом, конкатцирует их и, наконец, печатает свое собственное содержимое.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:output indent="yes" method="xml"/> 

    <xsl:template match="/exchange"> 
     <ImportTask> 
      <Courses> 
       <xsl:apply-templates select="//cbo_occl.cbo.srs"/> 
      </Courses> 
     </ImportTask> 
    </xsl:template> 

    <xsl:template match="cbo_occl.cbo.srs"> 
     <Course> 
      <!-- select all text-Nodes of vco_* elements --> 
      <xsl:for-each select="../../../*[matches(name(),'^vco_.*')]/text()"> 
       <xsl:value-of select="concat(.,'-')"/> 
      </xsl:for-each> 
      <xsl:value-of select="."/> 
     </Course>   
    </xsl:template> 

</xsl:stylesheet>  
+0

Thanks Leu! Отлично. – Jonah

+0

Не уверен, что я полностью понимаю весь синтаксис, но я могу найти его и работать назад для бит: Jonah

+0

Так что, я думаю, следующий вопрос: если мой XML был вложен дальше, скажите, там была другая организация, которая сидела ниже уровня CBO, и мне нужны были отдельные значения от этого объекта, тогда мне нужен еще один шаблон, и этот шаблон будет находиться в первом разделе: Jonah

0

У вас есть несколько различных спички шаблонов в вашем XSLT

<xsl:template match="/root"> 

<xsl:template match="CourseDetails"> 

<xsl:template match="CourseOcc"> 

Однако при использовании шаблона с матчем, они применяются только тогда, когда они соответствуют узлам в документе ввода XML. Вы не можете просто использовать произвольные имена здесь. Поскольку ваш входной XML не содержит элементов, называемых root, CourseDetails или CourseOcc, эти шаблоны никогда не вызываются.

Причина, по которой вы получаете вывод, который вы сейчас получаете, объясняется правилами XSLT built-in template, которые применяются, когда нет подходящих шаблонов для узла в вашем собственном XSLT (что здесь имеет место).

Что я думаю, что вы пытались сделать, на самом деле достигается с помощью «названных» шаблонов, которые позволят вам использовать произвольные имена. Таким образом, ваш XSLT будет более правильно написано так:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output indent="yes" method="xml"/> 
<xsl:template match="/"> 
    <ImportTask> 
     <xsl:call-template name="CourseDetails"/> 
     <xsl:text>-</xsl:text> 
     <xsl:call-template name="CourseOcc"/> 
    </ImportTask>  
</xsl:template> 

<xsl:template name="CourseDetails"> 
    <Courses> 
     <xsl:for-each select="exchange/vco/vco.srs"> 
      <Course> 
       <CourseCode><xsl:value-of select="vco_crsc.vco.srs"/></CourseCode> 
       <xsl:text>-</xsl:text> 
       <Programmecode><xsl:value-of select="vco_prgc.vco.srs"/></Programmecode> 
       <xsl:text>-</xsl:text> 
       <Routecode><xsl:value-of select="vco_rouc.vco.srs"/></Routecode> 
      </Course> 
     </xsl:for-each> 
    </Courses> 
</xsl:template> 

<xsl:template name="CourseOcc"> 
    <Occurences> 
     <xsl:for-each select="exchange/cbo/cbo.srs"> 
      <Occur> 
       <OccurCode><xsl:value-of select="cbo_occl.cbo.srs"/></OccurCode> 
      </Occur> 
     </xsl:for-each> 
    </Occurences> 
</xsl:template> 
</xsl:stylesheet> 

Обратите внимание, как первый шаблон еще матч шаблон, но один, который соответствует / и не /root, где / представляет собой «узел документа». Это шаблон, который сначала будет согласован XSLT.

Сказав это, вам фактически не нужно использовать именованные шаблоны здесь. Вы можете добиться того, чего хотите, с обычным сопоставлением шаблонов.Этот XSLT, вероятно, был бы предпочтительным в этом случае

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output indent="yes" method="xml"/> 

<xsl:template match="/exchange"> 
    <ImportTask> 
     <Courses> 
      <xsl:apply-templates select="vco/vco.srs"/> 
     </Courses> 
     <xsl:if test="cbo/cbo.srs"> 
      <xsl:text>-</xsl:text> 
      <Occurences> 
       <xsl:apply-templates select="cbo/cbo.srs"/> 
      </Occurences> 
     </xsl:if> 
    </ImportTask>  
</xsl:template> 

<xsl:template match="vco.srs"> 
    <Course> 
     <CourseCode><xsl:value-of select="vco_crsc.vco.srs"/></CourseCode> 
     <xsl:text>-</xsl:text> 
     <Programmecode><xsl:value-of select="vco_prgc.vco.srs"/></Programmecode> 
     <xsl:text>-</xsl:text> 
     <Routecode><xsl:value-of select="vco_rouc.vco.srs"/></Routecode> 
    </Course> 
</xsl:template> 

<xsl:template match="cbo.srs"> 
    <Occur> 
     <OccurCode><xsl:value-of select="cbo_occl.cbo.srs"/></OccurCode> 
    </Occur> 
</xsl:template> 
</xsl:stylesheet> 
+0

Привет Тим ​​ Спасибо, что посмотрели на это. Вы сделали очень хорошее объяснение того, чего я действительно не понимал. Я думаю, я могу видеть, где я ошибся и пропустил бит, который был нужен. – Jonah

Смежные вопросы