Xslt 基于元素属性类型对XML进行分类
使用此XML输入,我无法向特定部分添加元素Xslt 基于元素属性类型对XML进行分类,xslt,Xslt,使用此XML输入,我无法向特定部分添加元素 <Country> <info enum="CTRY" name="United Sates of America" total-states="50" /> <info enum="ST" name="New York" population="8,244,910"/> <info enum="ST" name="Chicago" population="2,707,120"/> <
<Country>
<info enum="CTRY" name="United Sates of America" total-states="50" />
<info enum="ST" name="New York" population="8,244,910"/>
<info enum="ST" name="Chicago" population="2,707,120"/>
<info enum="CTRY" name="Germany" total-states="16"/>
<info enum="ST" name="Berlin" population="3,469,910"/>
<info enum="ST" name="Brandenburg" population="2,500,000"/>
</Country>
这是我的XSL
<xsl:template match="/">
<Country>
<xsl:for-each select="Country/info">
<xsl:if test="@enum='CTRY'">
<CountryInfo>
<name>Country Name: <xsl:value-of select="@name"/></name>
<districts><xsl:value-of select="@total-states"></xsl:value-of></districts>
<xsl:for-each select="/Country/info">
<xsl:if test="@enum='ST'">
<state>
<stateName>State Name: <xsl:value-of select="@name"/></stateName>
<statePop>State Population: <xsl:value-of select="@population"/></statePop>
</state>
</xsl:if>
</xsl:for-each>
</CountryInfo>
</xsl:if>
</xsl:for-each>
</Country>
</xsl:template>
国家名称:
州名:
州人口:
问题是所有的州都为这两个国家而出现
这是我试图生成的XML输出
<Country>
<CountryInfo>
<name>Country Name: United Sates of America</name>
<districts>50</districts>
<state>
<stateName>State Name: New York</stateName>
<statePop>State Population: 8,244,910</statePop>
</state>
<state>
<stateName>State Name: Chicago</stateName>
<statePop>State Population: 2,707,120</statePop>
</state>
</CountryInfo>
<CountryInfo>
<name>Country Name: Germany</name>
<districts>16</districts>
<state>
<stateName>State Name: Berlin</stateName>
<statePop>State Population: 3,469,910</statePop>
</state>
<state>
<stateName>State Name: Brandenburg</stateName>
<statePop>State Population: 2,500,000</statePop>
</state>
</CountryInfo>
</Country>
国家名称:美利坚合众国
50
州名:纽约
州人口:8244910
州名:芝加哥
州人口:2707120
国家名称:德国
16
州名:柏林
州人口:3469910
州名:勃兰登堡
州人口:2500000
使用XSLT可以做到这一点吗?您的源代码严重滥用了XML!你应该向设计和提供这种垃圾的人抱怨 使用单个模板,您只能删除或扩展源中已有的元素 我相信这种转变能满足你的需要。它通过复制
Country
根元素并处理其内容来工作。第二个模板匹配所有info
元素,这些元素的enum
属性为CTRY
,构成CountryInfo
输出元素的基础
如果以下info
元素的enum
属性为ST
,则必须使用call template
递归地插入该元素中的信息,以获取状态信息
由于源数据的结构,此转换非常脆弱,如果存在任何意外元素,则会中断。请小心
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Country">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="info[@enum='CTRY']">
<CountryInfo>
<name>
<xsl:text>Country name: </xsl:text>
<xsl:value-of select="@name"/>
</name>
<districts>
<xsl:value-of select="@total-states"/>
</districts>
<xsl:call-template name="state"/>
</CountryInfo>
</xsl:template>
<xsl:template name="state">
<xsl:param name="i" select="1"/>
<xsl:if test="following-sibling::info[$i][@enum='ST']">
<state>
<stateName>
<xsl:text>State Name: </xsl:text>
<xsl:value-of select="following-sibling::info[$i]/@name"/>
</stateName>
<statePop>
<xsl:text>State Population: </xsl:text>
<xsl:value-of select="following-sibling::info[$i]/@population"/>
</statePop>
</state>
<xsl:call-template name="state">
<xsl:with-param name="i" select="$i+1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
国家名称:
州名:
州人口:
输出
<?xml version="1.0" encoding="utf-8"?>
<Country>
<CountryInfo>
<name>Country name: United States of America</name>
<districts>50</districts>
<state>
<stateName>State Name: New York</stateName>
<statePop>State Population: 8,244,910</statePop>
</state>
<state>
<stateName>State Name: Chicago</stateName>
<statePop>State Population: 2,707,120</statePop>
</state>
</CountryInfo>
<CountryInfo>
<name>Country name: Germany</name>
<districts>16</districts>
<state>
<stateName>State Name: Berlin</stateName>
<statePop>State Population: 3,469,910</statePop>
</state>
<state>
<stateName>State Name: Brandenburg</stateName>
<statePop>State Population: 2,500,000</statePop>
</state>
</CountryInfo>
</Country>
国家名称:美利坚合众国
50
州名:纽约
州人口:8244910
州名:芝加哥
州人口:2707120
国家名称:德国
16
州名:柏林
州人口:3469910
州名:勃兰登堡
州人口:2500000
您的源代码严重滥用了XML!你应该向设计和提供这种垃圾的人抱怨
使用单个模板,您只能删除或扩展源中已有的元素
我相信这种转变能满足你的需要。它通过复制Country
根元素并处理其内容来工作。第二个模板匹配所有info
元素,这些元素的enum
属性为CTRY
,构成CountryInfo
输出元素的基础
如果以下info
元素的enum
属性为ST
,则必须使用call template
递归地插入该元素中的信息,以获取状态信息
由于源数据的结构,此转换非常脆弱,如果存在任何意外元素,则会中断。请小心
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Country">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="info[@enum='CTRY']">
<CountryInfo>
<name>
<xsl:text>Country name: </xsl:text>
<xsl:value-of select="@name"/>
</name>
<districts>
<xsl:value-of select="@total-states"/>
</districts>
<xsl:call-template name="state"/>
</CountryInfo>
</xsl:template>
<xsl:template name="state">
<xsl:param name="i" select="1"/>
<xsl:if test="following-sibling::info[$i][@enum='ST']">
<state>
<stateName>
<xsl:text>State Name: </xsl:text>
<xsl:value-of select="following-sibling::info[$i]/@name"/>
</stateName>
<statePop>
<xsl:text>State Population: </xsl:text>
<xsl:value-of select="following-sibling::info[$i]/@population"/>
</statePop>
</state>
<xsl:call-template name="state">
<xsl:with-param name="i" select="$i+1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
国家名称:
州名:
州人口:
输出
<?xml version="1.0" encoding="utf-8"?>
<Country>
<CountryInfo>
<name>Country name: United States of America</name>
<districts>50</districts>
<state>
<stateName>State Name: New York</stateName>
<statePop>State Population: 8,244,910</statePop>
</state>
<state>
<stateName>State Name: Chicago</stateName>
<statePop>State Population: 2,707,120</statePop>
</state>
</CountryInfo>
<CountryInfo>
<name>Country name: Germany</name>
<districts>16</districts>
<state>
<stateName>State Name: Berlin</stateName>
<statePop>State Population: 3,469,910</statePop>
</state>
<state>
<stateName>State Name: Brandenburg</stateName>
<statePop>State Population: 2,500,000</statePop>
</state>
</CountryInfo>
</Country>
国家名称:美利坚合众国
50
州名:纽约
州人口:8244910
州名:芝加哥
州人口:2707120
国家名称:德国
16
州名:柏林
州人口:3469910
州名:勃兰登堡
州人口:2500000
您正在生成所有州的完整列表,因为在您的
中有另一个
通过使用/Country/info
跳到根节点来选择所有州
在本例中,对于每个“country”元素,您要查找具有@enum='ST'的所有info
元素,其中前一个最近的info元素具有
@enum='CTRY'`是当前生成“states”的元素
不要从“拉”的方式来处理它,而是着眼于“推”正确的内容并匹配应用的模式。它将使您的XSLT更容易生成,并帮助模块化为易于维护的独特模板(并且在导入时更容易覆盖)
州名:
州人口:
您正在生成所有州的完整列表,因为在您的
中有另一个
通过使用/Country/info
跳到根节点来选择所有州
在本例中,对于每个“country”元素,您希望找到所有info
元素,其中@enum='ST'的前一个info元素最接近
<Country>
<info enum="CTRY" name="United Sates of America" total-states="50" />
<info enum="ST" name="New York" population="8,244,910"/>
<info enum="ST" name="Chicago" population="2,707,120"/>
<info enum="CTRY" name="Germany" total-states="16"/>
<info enum="ST" name="Berlin" population="3,469,910"/>
<info enum="ST" name="Brandenburg" population="2,500,000"/>
</Country>
<Country>
<CountryInfo>
<name>Country Name: United Sates of America</name>
<districts>50</districts>
<state>
<stateName>State Name:New York</stateName>
<statePop>State Population: 8,244,910</statePop>
</state>
<state>
<stateName>State Name:Chicago</stateName>
<statePop>State Population: 2,707,120</statePop>
</state>
</CountryInfo>
<CountryInfo>
<name>Country Name: Germany</name>
<districts>16</districts>
<state>
<stateName>State Name:Berlin</stateName>
<statePop>State Population: 3,469,910</statePop>
</state>
<state>
<stateName>State Name:Brandenburg</stateName>
<statePop>State Population: 2,500,000</statePop>
</state>
</CountryInfo>
</Country>