По существу у меня есть 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>
В духе 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>
<xsl:apply-templates select=".//B"/>
может быть проблемой IMO. вероятно, вам нужно вызвать шаблон.
//B означает Root/B.
Поправьте меня, если я ошибаюсь.
В вашем примере путь 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.