【问题标题】:XML to XML using XSLT - transforming similar parent nodes使用 XSLT 将 XML 转换为 XML - 转换相似的父节点
【发布时间】:2013-02-17 02:36:17
【问题描述】:

我有以下 XML:

<EMPLOYEE_LIST>
    <EMPLOYEES_01>
        <PERMANENT>
            <EMPID>650000</EMPID>
            <FIRST_NAME>KEITH</FIRST_NAME>
            <MIDDLE_NAME>H</MIDDLE_NAME>
            <LAST_NAME>ROGERS</LAST_NAME>
        </PERMANENT>
        <CONTRACTUAL>
            <EMPID>650001</EMPID>
            <FIRST_NAME>DARRYL</FIRST_NAME>
            <MIDDLE_NAME>Y</MIDDLE_NAME>
            <LAST_NAME>HANNAH</LAST_NAME>
        </CONTRACTUAL>
    </EMPLOYEES_01>
    <EMPLOYEES_02>
        <PERMANENT>
            <EMPID>650002</EMPID>
            <FIRST_NAME>KEITH</FIRST_NAME>
            <MIDDLE_NAME>ROGERS</MIDDLE_NAME>
            <LAST_NAME>H</LAST_NAME>
        </PERMANENT>
        <CONTRACTUAL>
            <EMPID>650003</EMPID>
            <FIRST_NAME>DARRYL</FIRST_NAME>
            <MIDDLE_NAME>HANNAH</MIDDLE_NAME>
            <LAST_NAME>Y</LAST_NAME>
        </CONTRACTUAL>
    </EMPLOYEES_02>
</EMPLOYEE_LIST>

我正在使用以下 XML 对其进行转换:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/EMPLOYEE_LIST">
        <employees>
            <xsl:apply-templates select="EMPLOYEES/node()"/>
        </employees>        
    </xsl:template>    
    <xsl:template match="PERMANENT">
        <permanent>
            <xsl:apply-templates select="*"/>
        </permanent>
    </xsl:template>    
    <xsl:template match="EMPID">
        <emp_id>
            <xsl:value-of select="."/>
        </emp_id>
    </xsl:template>    
    <xsl:template match="FIRST_NAME">
        <f_name>
            <xsl:value-of select="."/>
        </f_name>
    </xsl:template>    
    <xsl:template match="MIDDLE_NAME">
        <m_name>
            <xsl:value-of select="."/>
        </m_name>
    </xsl:template>    
    <xsl:template match="LAST_NAME">
        <l_name>
            <xsl:value-of select="."/>
        </l_name>
    </xsl:template>

    <xsl:template match="CONTRACTUAL">
        <permanent>
            <xsl:apply-templates select="*"/>
        </permanent>
    </xsl:template>    
    <xsl:template match="EMPID">
        <emp_id>
            <xsl:value-of select="."/>
        </emp_id>
    </xsl:template>    
    <xsl:template match="FIRST_NAME">
        <f_name>
            <xsl:value-of select="."/>
        </f_name>
    </xsl:template>    
    <xsl:template match="MIDDLE_NAME">
        <m_name>
            <xsl:value-of select="."/>
        </m_name>
    </xsl:template>    
    <xsl:template match="LAST_NAME">
        <l_name>
            <xsl:value-of select="."/>
        </l_name>
    </xsl:template>
</xsl:stylesheet>

期望转换后的 XML 具有以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<employees>
    <employee>
        <emp_id>650000</emp_id>
        <f_name>KEITH</f_name>
        <m_name>H</m_name>
        <l_name>ROGERS</l_name>
        <type>permanent</type>
        <emp_id>650001</emp_id>
        <f_name>DARRYL</f_name>
        <m_name>Y</m_name>
        <l_name>HANNAH</l_name>
        <type>contractual</type>
        <emp_id>650002</emp_id>
        <f_name>KEITH</f_name>
        <m_name>ROGERS</m_name>
        <l_name>H</l_name>
        <type>permanent</type>
        <emp_id>650003</emp_id>
        <f_name>DARRYL</f_name>
        <m_name>HANNAH</m_name>
        <l_name>Y</l_name>
        <type>contractual</type>
    </employee>
</employees>

到目前为止我还没有成功,因为我是新手,任何帮助都将不胜感激

谢谢

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    我将在这里使用 Dimitre 对您上一个问题的回答作为基础,因为它比我的更简洁:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my" exclude-result-prefixes="my">
      <xsl:output omit-xml-declaration="yes" indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <my:Renames>
        <n old="EMPLOYEES" new="employees"/>
        <n old="EMPID" new="emp_id"/>
        <n old="FIRST_NAME" new="f_name"/>
        <n old="MIDDLE_NAME" new="m_name"/>
        <n old="LAST_NAME" new="l_name"/>
        <n old="PERMANENT" new="permanent"/>
        <n old="CONTRACTUAL" new="contractual"/>
      </my:Renames>
    
      <xsl:variable name="vRenames" select="document('')/*/my:Renames/*"/>
    
      <xsl:template match="EMPLOYEE_LIST">
        <employees>
          <employee>
            <xsl:apply-templates select="*/*" />
          </employee>
        </employees>
      </xsl:template>
    
      <xsl:template match="*/*" priority="-1">
        <xsl:element name="{$vRenames[@old = name(current())]/@new}">
          <xsl:apply-templates/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="PERMANENT|CONTRACTUAL">
        <xsl:apply-templates/>
        <type>
          <xsl:value-of select="$vRenames[@old = name(current())]/@new"/>
        </type>
      </xsl:template>
    </xsl:stylesheet>
    

    新的部分是这样的:

      <xsl:template match="EMPLOYEE_LIST">
        <employees>
          <employee>
            <xsl:apply-templates select="*/*" />
          </employee>
        </employees>
      </xsl:template>
    

    当在上面的示例输入上运行时,会产生:

    <employees>
      <employee>
        <emp_id>650000</emp_id>
        <f_name>KEITH</f_name>
        <m_name>H</m_name>
        <l_name>ROGERS</l_name>
        <type>permanent</type>
        <emp_id>650001</emp_id>
        <f_name>DARRYL</f_name>
        <m_name>Y</m_name>
        <l_name>HANNAH</l_name>
        <type>contractual</type>
        <emp_id>650002</emp_id>
        <f_name>KEITH</f_name>
        <m_name>ROGERS</m_name>
        <l_name>H</l_name>
        <type>permanent</type>
        <emp_id>650003</emp_id>
        <f_name>DARRYL</f_name>
        <m_name>HANNAH</m_name>
        <l_name>Y</l_name>
        <type>contractual</type>
      </employee>
    </employees>
    

    【讨论】:

      【解决方案2】:

      更短且更“推式”的解决方案:稍微调整一下我对上一个问题的回答:

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       xmlns:my="my:my" exclude-result-prefixes="my">
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
       <my:Renames>
        <n old="EMPID" new="emp_id"/>
        <n old="FIRST_NAME" new="f_name"/>
        <n old="MIDDLE_NAME" new="m_name"/>
        <n old="LAST_NAME" new="l_name"/>
        <n old="PERMANENT" new="permanent"/>
        <n old="CONTRACTUAL" new="contractual"/>
       </my:Renames>
      
       <xsl:variable name="vRenames" select="document('')/*/my:Renames/*"/>
      
       <xsl:template match="EMPLOYEE_LIST">
        <employees><employee><xsl:apply-templates/></employee></employees>
       </xsl:template>
      
       <xsl:template match="*/*/*" priority="-1">
           <xsl:element name="{$vRenames[@old = name(current())]/@new}">
             <xsl:apply-templates/>
           </xsl:element>
       </xsl:template>
      
       <xsl:template match="PERMANENT|CONTRACTUAL">
        <xsl:apply-templates/>
        <type><xsl:value-of select="$vRenames[@old = name(current())]/@new"/></type>
       </xsl:template>
      </xsl:stylesheet>
      

      将此转换应用于提供的 XML 文档时:

      <EMPLOYEE_LIST>
          <EMPLOYEES_01>
              <PERMANENT>
                  <EMPID>650000</EMPID>
                  <FIRST_NAME>KEITH</FIRST_NAME>
                  <MIDDLE_NAME>H</MIDDLE_NAME>
                  <LAST_NAME>ROGERS</LAST_NAME>
              </PERMANENT>
              <CONTRACTUAL>
                  <EMPID>650001</EMPID>
                  <FIRST_NAME>DARRYL</FIRST_NAME>
                  <MIDDLE_NAME>Y</MIDDLE_NAME>
                  <LAST_NAME>HANNAH</LAST_NAME>
              </CONTRACTUAL>
          </EMPLOYEES_01>
          <EMPLOYEES_02>
              <PERMANENT>
                  <EMPID>650002</EMPID>
                  <FIRST_NAME>KEITH</FIRST_NAME>
                  <MIDDLE_NAME>ROGERS</MIDDLE_NAME>
                  <LAST_NAME>H</LAST_NAME>
              </PERMANENT>
              <CONTRACTUAL>
                  <EMPID>650003</EMPID>
                  <FIRST_NAME>DARRYL</FIRST_NAME>
                  <MIDDLE_NAME>HANNAH</MIDDLE_NAME>
                  <LAST_NAME>Y</LAST_NAME>
              </CONTRACTUAL>
          </EMPLOYEES_02>
      </EMPLOYEE_LIST>
      

      产生了想要的正确结果:

      <employees>
         <employee>
            <emp_id>650000</emp_id>
            <f_name>KEITH</f_name>
            <m_name>H</m_name>
            <l_name>ROGERS</l_name>
            <type>permanent</type>
            <emp_id>650001</emp_id>
            <f_name>DARRYL</f_name>
            <m_name>Y</m_name>
            <l_name>HANNAH</l_name>
            <type>contractual</type>
            <emp_id>650002</emp_id>
            <f_name>KEITH</f_name>
            <m_name>ROGERS</m_name>
            <l_name>H</l_name>
            <type>permanent</type>
            <emp_id>650003</emp_id>
            <f_name>DARRYL</f_name>
            <m_name>HANNAH</m_name>
            <l_name>Y</l_name>
            <type>contractual</type>
         </employee>
      </employees>
      

      【讨论】:

      • 如果我将父节点名称从 EMPLOYEES_02 修改为 ESTRANGED_02,您的建议会起作用吗?
      • @ReggieMiller,是的,试试看 :)
      • 尚未对整个 XML 进行尝试,但您能告诉我是否有办法在转换过程中截断/删除不需要的元素?假设我想在转换过程中截断 l_name,以便生成的 xml 只有 f_name/m_name?可以在这段代码中完成吗?
      • @ReggieMiller,当然可以,但这是另一个新问题 :) 请参阅我对这个问题的回答:stackoverflow.com/questions/321860/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      • 1970-01-01
      • 1970-01-01
      • 2014-07-16
      • 2019-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多