Написание XSLT для источника и цели XML - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть источник и цель XML, и я должен написать XSLT для преобразования. У меня трудности с сопоставлением компонентов для XSLT для детали Y в цели xml.

Источник xml:

<A id="123" name="a">
    <B>
        <d id="p123" name="one">
            <f>Hello</f>
            <e ref="c123" />
        </d>
        <d id="p234" name="two">
            <f>Hello</f>
            <e ref="c234" />
            <e ref="c123" />
        </d>
    </B>
    <C>
        <e id="c123" type="paragraph"><text>Dummy Text</text></e>
        <e id="c234" type="link" url="google.com"/>
    </C>
</A>

Цель xml:

<X id="123" name="a">
    <Y id="p123" name="one">
        <f>Hello</f>
        <content id="c123" type="TEXT"><text>Dummy Text</text></content >
    </Y>
    <Y id="p234" name="two">
        <f>Hello</f>
        <content id="c234" type="link" url="google.com"/>
        <content id="c123" type="paragraph"><text>Dummy Text</text></content >
    </Y>
</X>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl= "http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
         <xsl:apply-templates select="A" />
    </xsl:template> 
    <xsl:template match="A" >
     <X id="@id" name="@name">
            <xsl:for-each select="A/B/d" >
             <Y id="@id" name="@name">

             </Y>
            </xsl:for-each>
     </X>

    </xsl:template>
</xsl:stylesheet>

Ответы [ 3 ]

1 голос
/ 08 апреля 2020

Вы можете использовать эту таблицу стилей XSLT-1.0:

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

    <xsl:template match="A" >
      <X id="{@id}" name="{@name}">
        <xsl:apply-templates select="B/d" />
      </X>
    </xsl:template>

    <xsl:template match="d" >
      <Y id="{@id}" name="{@name}">
        <xsl:copy-of select="f" />      
        <xsl:apply-templates select="e" />
      </Y>
    </xsl:template>

    <xsl:template match="e" >
      <content>
        <xsl:copy-of select="/A/C/e[current()/@ref = @id]/@* | /A/C/e[current()/@ref = @id]/*" />
      </content>
    </xsl:template>

</xsl:stylesheet>

Его вывод

<?xml version="1.0"?>
<X id="123" name="a">
  <Y id="p123" name="one">
    <f>Hello</f>
    <content id="c123" type="paragraph">
      <text>Dummy Text</text>
    </content>
  </Y>
  <Y id="p234" name="two">
    <f>Hello</f>
    <content id="c234" type="link" url="google.com"/>
    <content id="c123" type="paragraph">
      <text>Dummy Text</text>
    </content>
  </Y>
</X>

Первый тип <content> не является "TEXT", потому что это будет были нерегулярными. Я предположил, что вам нужен обычный вывод.


Если скорость критична, вы можете реализовать оптимизацию, предложенную в комментариях:

  • Добавить xsl:key на верхнем уровне:

    <xsl:key name="ids" match="/A/C/e" use="@id" />
    
  • И доступ к нему в шаблоне e

    <xsl:copy-of select="key('ids',current()/@ref)/@* | key('ids',current()/@ref)/@*" />
    

Это все еще выполняет поиск дважды. Если вас это беспокоит, вы можете кэшировать результат xsl:key в переменной.

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

Вот еще один вариант, который использует xsl: key, если важна эффективность. Это также стиль 100% pu sh.

Это немного многословно, но также довольно просто следовать / поддерживать.

XSLT 1.0

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

  <xsl:key name="content" match="e[@id]" use="@id"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="A">
    <X>
      <xsl:apply-templates select="@*|B/*"/>
    </X>
  </xsl:template>

  <xsl:template match="d">
    <Y>
      <xsl:apply-templates select="@*|node()"/>
    </Y>
  </xsl:template>

  <xsl:template match="e[@ref]">
    <content>
      <xsl:apply-templates select="key('content',@ref)"/>
    </content>
  </xsl:template>

  <xsl:template match="e[@id]">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:template>

</xsl:stylesheet>

Скрипка: http://xsltfiddle.liberty-development.net/naZXVEV

0 голосов
/ 08 апреля 2020

В вашем вопросе отсутствуют части необходимого сопоставления, но я думаю, что вы можете начать с этого.

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

    <xsl:template match="/">
         <xsl:apply-templates select="A" />
    </xsl:template>

    <xsl:template match="A" >
     <X id="{@id}" name="{@name}">
        <xsl:for-each select="B/d" >
             <Y id="{@id}" name="{@name}">
                <xsl:copy-of select="f"/>
                <xsl:for-each select="e">
                    <content id="{@ref}"/>
                </xsl:for-each>
             </Y>
        </xsl:for-each>
     </X>
    </xsl:template>
</xsl:stylesheet>

Посмотрите, как это работает здесь: https://xsltfiddle.liberty-development.net/naZXVEU

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