Рекурсивный XML через XSLT к XML

По существу у меня есть XML, структурированный как это:

<A>
 <B>
  <1>data</1>
  <2>data</2>
  <C>
   <1>data</1>
   <2>data</2>
   <B>
    <1>data</1>
    <2>data</2>
    <C>
     <B>
      <1>data</1>
      <2>data</2>
     </B>
    </C>
   </B>
   <B>
    <1>data</1>
    <2>data</2>
   </B>
  </C>
 </B>
</A>

Я пытаюсь заставить вывод быть похожим на это:

<A>
<B 1="data" 2="data">
    <C 1="data" 2="data">
        <B 1="data" 2="data">
            <C>
                <B 1="data" 2="data" >
                </B>
            </C>
        </B>
        <B 1="data" 2="data" >
        </B>
    </C>
</B>
</A>

Я выяснил, как поместить все как атрибуты и запустить цикличное выполнение через элементы. Проблема, с которой я сталкиваюсь, - то, что при попытке добраться ниже первого C, ничего не происходит. Вот мой код:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <MenuDataResult>
      <B>
        <xsl:apply-templates />
      </B>
    </MenuDataResult>
  </xsl:template>

  <xsl:template match="B">
        <xsl:for-each select="B">
          <B ItemID="{B/ItemID/text()}" ItemType="{ItemType/text()}" ItemSubType="{ItemSubType/text()}"
                  ItemTitle="{ItemTitle/text()}" ItemImage="{ItemImage/text()}" ItemImageOverride="{ItemImageOverride/text()}"
                ItemLink="{ItemLink/text()}" ItemTarget="{ItemTarget/text()}>">
            <xsl:for-each select="C">
              <xsl:apply-templates select="C"/>
            </xsl:for-each>
          </B>
        </xsl:for-each>
  </xsl:template>

  <xsl:template match="C">
    <C ID="{ID/text()}" Title="{Title/text()}" Template="{Template/text()}"
          Type="{Type/text()}" Link="{Link/text()}" ParentID="{ParentID/text()}"
          AncestorID="{AncestorID/text()}" FolderID="{FolderID/text()}" Description="{Description/text()}"
          Image="{Image/text()}" ImageOverride="{ImageOverride/text()}">
      <xsl:for-each select="B">
        <xsl:apply-templates select=".//B"/>
      </xsl:for-each>
    </C>
  </xsl:template>

</xsl:stylesheet>
1
задан Evidica 10 June 2010 в 21:22
поделиться

3 ответа

В духе XSLT: это преобразование :

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

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

 <xsl:template match="a1|a2">
  <xsl:attribute name="{name()}">
    <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

при применении к исправленному XML-документу из примера Алехандро :

<A>
 <B>
  <a1>data</a1>
  <a2>data</a2>
  <C>
   <a1>data</a1>
   <a2>data</a2>
   <B>
    <a1>data</a1>
    <a2>data</a2>
    <C>
     <B>
      <a1>data</a1>
      <a2>data</a2>
     </B>
    </C>
   </B>
   <B>
    <a1>data</a1>
    <a2>data</a2>
   </B>
  </C>
 </B>
</A>

дает желаемый правильный результат ]:

<A>
   <B a1="data" a2="data">
      <C a1="data" a2="data">
         <B a1="data" a2="data">
            <C>
               <B a1="data" a2="data"/>
            </C>
         </B>
         <B a1="data" a2="data"/>
      </C>
   </B>
</A>
1
ответ дан 2 September 2019 в 23:49
поделиться
<xsl:apply-templates select=".//B"/>

может быть проблемой IMO. вероятно, вам нужно вызвать шаблон.

//B означает Root/B.

Поправьте меня, если я ошибаюсь.

0
ответ дан 2 September 2019 в 23:49
поделиться

В вашем примере путь A / B / C / B / C / B / 1 = data

<xsl:template match="C">
    # context() = A/B/C
.. 
  <xsl:for-each select="B">
    # context() = A/B/C/B
    # selects every B descendent of the current B
    <xsl:apply-templates select=".//B"/>
       # context() = A/B/C/B/C/B/
  </xsl:for-each>
</xsl:template>


<xsl:template match="B">
  # context() = A/B/C/B/C/B/
  <xsl:for-each select="B">
     # there are no B's under this B - only 1 and 2 so nothing selected
  </xsl:for-each>
</xsl:template>

Кажется, вы вкладываете больше для каждого и выбираете глубже, чем вам нужно. Просто имея в вашем шаблоне C для обработки любых напрямую вложенных B или C, и то же самое внутри вашего шаблона B. На данный момент он выбирает только B из B внутри B.

1
ответ дан 2 September 2019 в 23:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: