Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xslt 基于元素属性类型对XML进行分类_Xslt - Fatal编程技术网

Xslt 基于元素属性类型对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"/> <

使用此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"/>
  <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>