我有一个使用xml的对象菜单。我想从我的数据库生成xml,但是对象希望它的信息是属性而不是元素。
问题不在于将元素转换为属性,而是我能做到的。问题是子菜单的深度不明确,每个菜单项可以是实际菜单项,也可以是子菜单的父项,或两者兼而有之。
是否可以在Xslt中执行此操作?
启动XML
<MenuDataSet>
<Menu>
<ChildID>0</ChildID>
<ParentID></ParentID>
<Title>Main Menu</Title>
<PageURL></PageURL>
<Menu>
<ChildID>2</ChildID>
<ParentID>0</ParentID>
<Title>Title 2</Title>
<PageURL>pageurl2.com</PageURL>
<SortOrder>3</SortOrder>
<Menu>
<ChildID>3</ChildID>
<ParentID>2</ParentID>
<Title>Title 3</Title>
<PageURL>Pageurl3.com</PageURL>
<SortOrder>9</SortOrder>
<Menu>
<ChildID>4</ChildID>
<ParentID>3</ParentID>
<Title>Title 4</Title>
<PageURL>Pageurl4.com</PageURL>
<SortOrder>1</SortOrder>
</Menu>
</Menu>
</Menu>
<Menu>
<ChildID>1</ChildID>
<ParentID>0</ParentID>
<Title>Title 1</Title>
<PageURL>Pageurl1.com</PageURL>
<SortOrder>4</SortOrder>
<BaseModel>AX25L</BaseModel>
</Menu>
</Menu>
</MenuDataSet>
所需的结果XML(可以包含额外的元素,如ChildID,ParentID,SortOrder,但是我不想这样做)
<MenuDataSet>
<Menu Title="Main Menu">
<Menu Title="Title 2" PageURL="pageurl2.com">
<Menu Title="Title 3" PageURL="pageurl3.com">
<Menu Title="Title 4" PageURL="pageurl4.com"/>
</Menu>
</Menu>
</Menu>
<Menu Title="Title 1" PageURL="pagurl1.com"/>
</MenuDataSet>
提前致谢!
答案 0 :(得分:0)
首先使用identity transform,然后根据需要覆盖......
XML
<MenuDataSet>
<Menu>
<ChildID>0</ChildID>
<ParentID></ParentID>
<Title>Main Menu</Title>
<PageURL></PageURL>
<Menu>
<ChildID>2</ChildID>
<ParentID>0</ParentID>
<Title>Title 2</Title>
<Menu>
<ChildID>3</ChildID>
<ParentID>2</ParentID>
<Title>Title 3</Title>
<PageURL>Pageurl3.com</PageURL>
<SortOrder>9</SortOrder>
<Menu>
<ChildID>4</ChildID>
<ParentID>3</ParentID>
<Title>Title 4</Title>
<PageURL>Pageurl4.com</PageURL>
<SortOrder>1</SortOrder>
</Menu>
</Menu>
<PageURL>pageurl2.com</PageURL>
<SortOrder>3</SortOrder>
</Menu>
<Menu>
<ChildID>1</ChildID>
<ParentID>0</ParentID>
<Title>Title 1</Title>
<PageURL>Pageurl1.com</PageURL>
<SortOrder>4</SortOrder>
<BaseModel>AX25L</BaseModel>
</Menu>
</Menu>
</MenuDataSet>
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:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Menu">
<xsl:copy>
<xsl:apply-templates select="@*|Title[string()]|PageURL[string()]"/>
<xsl:apply-templates select="Menu"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Title|PageURL">
<xsl:attribute name="{local-name()}">
<xsl:apply-templates/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
<MenuDataSet>
<Menu Title="Main Menu">
<Menu Title="Title 2" PageURL="pageurl2.com">
<Menu Title="Title 3" PageURL="Pageurl3.com">
<Menu Title="Title 4" PageURL="Pageurl4.com"/>
</Menu>
</Menu>
<Menu Title="Title 1" PageURL="Pageurl1.com"/>
</Menu>
</MenuDataSet>
如果您使用的是XSLT 2.0,则可以简化Menu
模板...
<xsl:template match="Menu">
<xsl:copy>
<xsl:apply-templates select="(@*,(Title|PageURL)[string()],Menu)"/>
</xsl:copy>
</xsl:template>
答案 1 :(得分:0)
XSLT实际上非常擅长处理XML数据结构的常常递归性质。
例如,这个XSLT样式表应该产生你想要的结果XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="MenuDataSet">
<MenuDataSet>
<xsl:apply-templates select="Menu" />
</MenuDataSet>
</xsl:template>
<xsl:template match="Menu">
<Menu Title="{Title}">
<xsl:if test="PageURL != ''">
<xsl:attribute name="PageURL"><xsl:value-of select="PageURL"/></xsl:attribute>
</xsl:if>
<xsl:apply-templates select="Menu" />
</Menu>
</xsl:template>
</xsl:stylesheet>
诀窍是使用可在任何子节点上应用的模板。此模板中的关键字是<xsl:apply-templates select="Menu" />
元素。它负责以递归方式调用菜单模板(在我们的例子中)。
答案 2 :(得分: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="*">
<xsl:copy>
<xsl:apply-templates select="Menu | (Title | PageURL) [string()]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Title | PageURL">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>