извлечь дочерний узел для создания XML с соответствующим родительским узлом - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть входной XML, подобный следующей структуре.

<Root>
    <STDS>
        <DEPT>111</DEPT>
        <COD>123</COD>
        <PIN>100</PIN>
    </STDS>
    <STDS>
        <DEPT>222</DEPT>
        <COD>234</COD>
        <PIN>200</PIN>
        <DETS>
            <NAM>ABC</NAM>
            <AGE>20</AGE>
        </DETS>
    </STDS>
    <STDS>
        <DEPT>333</DEPT>
        <COD>345</COD>
        <PIN>300</PIN>
        <DETS>
            <NAM>XYZ</NAM>
            <AGE>21</AGE>
        </DETS>
        <DETS>
            <NAM>ZZZ</NAM>
            <AGE>21</AGE>
        </DETS>
    </STDS>
</Root>

Я использую следующий код для решения этой проблемы.Я использую цикл for-each, все преобразуют все STDS, в то время как другой for-each извлекает дочерние DETS и объединяет их с родительскими узлами DETS.Но из-за каждого они дают все узлы вместе.в то время как дочерние узлы (DETS) должны быть чуть ниже соответствующего родительского узла.

<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:ns0="Students" xmlns:s0="STDS" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:template match="/">
    <xsl:apply-templates select="/s0:Root" />
  </xsl:template>
<xsl:template match="/s0:Root">
    <ns0:Students>

      <xsl:for-each select="s0:Root/s0:STDS">
       <Students>
            <Department>
                <xsl:value-of select="s0:DEPT" />
            </Department>
            <Code>
                <xsl:value-of select="s0:COD" />
            </Code>
            <Pin>
                <xsl:value-of select="s0:PIN" /></Pin>
            <Details>
                <Name><xsl:value-of select="NAM" /></Name>
                <Age><xsl:value-of select="AGE" /></Age>
            </Details>
        </Students>
      </xsl:for-each>

     <xsl:for-each select="s0:STDS/s0:DETS">
        <Students>
            <Department>
                <xsl:value-of select="../DEPT" />
            </Department>
            <Code>
                <xsl:value-of select="../COD" />
            </Code>
            <Pin>
                <xsl:value-of select="../PIN" />
            </Pin>
            <Details>
                <Name><xsl:value-of select="s0:NAM" /></Name>
                <Age><xsl:value-of select="s0:AGE" /></Age>
            </Details>
        </Students>
      </xsl:for-each>

Я получаю следующий вывод.Благодаря for-каждому все извлеченные узлы находятся в конце.

<Students>
    <Department>222</Department>
    <Code>234</Code>
    <Pin>200</Pin>
</Students>
<Students>
    <Department>333</Department>
    <Code>345</Code>
    <Pin>300</Pin>
</Students>
<Students>
    <Department>222</Department>
    <Code>234</Code>
    <Pin>200</Pin>
    <Details>
        <Name>ABC</Name>
        <Age>20</Age>
    </Details>
</Students>
<Students>
    <Department>333</Department>
    <Code>345</Code>
    <Pin>300</Pin>
    <Details>
        <Name>XYZ</Name>
        <Age>21</Age>
    </Details>
</Students>
<Students>
    <Department>333</Department>
    <Code>345</Code>
    <Pin>300</Pin>
    <Details>
        <Name>ZZZ</Name>
        <Age>21</Age>
    </Details>
</Students>

Пока ожидаемый результат следующий.

<Students>
    <Department>111</Department>
    <Code>123</Code>
    <Pin>100</Pin>
</Students>
<Students>
    <Department>222</Department>
    <Code>234</Code>
    <Pin>200</Pin>
</Students>
<Students>
    <Department>222</Department>
    <Code>234</Code>
    <Pin>200</Pin>
    <Details>
        <Name>ABC</Name>
        <Age>20</Age>
    </Details>
</Students>
<Students>
    <Department>333</Department>
    <Code>345</Code>
    <Pin>300</Pin>
</Students>
<Students>
    <Department>333</Department>
    <Code>345</Code>
    <Pin>300</Pin>
    <Details>
        <Name>XYZ</Name>
        <Age>21</Age>
    </Details>
</Students>
<Students>
    <Department>333</Department>
    <Code>345</Code>
    <Pin>300</Pin>
    <Details>
        <Name>ZZZ</Name>
        <Age>21</Age>
    </Details>
</Students>

Ответы [ 3 ]

1 голос
/ 12 апреля 2019

Не используйте несколько xsl:for-each (обычно это парадигма языков прикладного уровня, использующих циклы, а не рекурсивный стиль XSLT) и обрабатывайте потребности с помощью шаблонов, условно применяя узел Подробности , если он существует:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/Root">
    <xsl:copy>    
      <xsl:apply-templates select="STDS"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="STDS">
    <Students>    
      <Department><xsl:value-of select="DEPT"/></Department>
      <Code><xsl:value-of select="COD"/></Code>
      <Pin><xsl:value-of select="PIN"/></Pin>
    </Students>  
    <xsl:apply-templates select="DETS"/>
  </xsl:template>

  <xsl:template match="DETS">
    <Students>    
      <Department><xsl:value-of select="../DEPT"/></Department>
      <Code><xsl:value-of select="../COD"/></Code>
      <Pin><xsl:value-of select="../PIN"/></Pin>
      <Details>
        <Name><xsl:value-of select="NAM"/></Name>
        <Age><xsl:value-of select="AGE"/></Age>
     </Details>
     </Students>
  </xsl:template>

</xsl:transform>

XSLT Demo

1 голос
/ 12 апреля 2019

Это довольно странное требование, но оно может быть достигнуто довольно просто:

XSLT 1.0

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

<xsl:template match="/Root">
    <xsl:for-each select="STDS">
        <xsl:variable name="common">
            <Department>
                <xsl:value-of select="DEPT" />
            </Department>
            <Code>
                <xsl:value-of select="COD" />
            </Code>
            <Pin>
                <xsl:value-of select="PIN" />
            </Pin>
        </xsl:variable>
        <!-- DEPARTMENT -->
        <Students>
            <xsl:copy-of select="$common"/>
        </Students>
        <!-- STUDENTS -->
        <xsl:for-each select="DETS">
            <Students>
                <xsl:copy-of select="$common"/>
                <Details>
                    <Name>
                        <xsl:value-of select="NAM" />
                    </Name>
                    <Age>   
                        <xsl:value-of select="AGE" />
                    </Age>
                </Details>
            </Students>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Обратите внимание, что результатом является фрагмент XML (без единого корневого элемента).

0 голосов
/ 12 апреля 2019

В Mapper все, что вам нужно сделать, это подключить <DETS> к <Students> через петлевой функтоид .

Вот и все, пользовательский xslt не требуется.

Одно примечание: в зависимости от состава схемы вам может понадобиться другой петлевой функтоид от <STDS> до <Student>.Попробовать разные комбинации очень просто.

Хотя они могут быть технически правильными, ответы Xsl не являются правильным способом сделать это в BizTalk .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...