XSLT:如何复制父节点而不改变,转换子节点

5

我是XSLT的新手,所以这可能很基础,但我真的需要一些输入。我需要转换我的xml中的子节点,但同时保持父节点不变。我的xml如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XMLTest xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xmlns:jfxpf="http://www.xfa.com/schema/xml-package" xmlns:xfa="http://www.xfa.com/schema/xfa-data">
    <result form="10"   version="4" resultid="23146" respondent="ycisxmir" authid="" date="2012-09-12 06:39:44" times="462">
        <Q0061 answerid="1">1</Q0061>
        <Q0060 answerid="2">2</Q0060>
        <QTXT1>1</QTXT1>
    </result>
</XMLTest>

我需要保留XMLTest和result两个顶级节点,但子节点需要转换为更通用的格式,例如这样:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XMLTest xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xmlns:jfxpf="http://www.xfa.com/schema/xml-package" xmlns:xfa="http://www.xfa.com/schema/xfa-data">
    <result form="10"   version="4" resultid="23146" respondent="ycisxmir" authid="" date="2012-09-12 06:39:44" times="462">
        <answer>Q0061</answer>
        <id>1</id>
        <value>1</value>
        <answer>Q0060</answer>
        <id>2</id>
        <value>2</value>
        <answer>QTXT1</answer>
        <value>1</value>
    </result>
</XMLTest>

到目前为止,我的XSLT看起来像这样:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="result/*">
        <answer><xsl:value-of select="local-name()"/></answer> 
        <id><xsl:value-of select="@answerid"/></id> 
        <value><xsl:value-of select="@*"/></value> 
    </xsl:template>  
</xsl:stylesheet>

我尝试在顶层节点上使用xsl:copy,但是无法保留子节点或子节点的转换效果。我该如何同时保留顶层节点并强制对其进行转换?


不错的尝试,已点赞!只是你缺少复制其他节点的身份模板。请查看我的答案。 - Rookie Programmer Aravind
我已经更新了答案并添加了注释,请查看。 - Rookie Programmer Aravind
2个回答

3

从以下几点开始:

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

现在,您需要添加所需转换的模板,即:
<xsl:template match="result/*[@answerid]">
        <answer><xsl:value-of select="local-name()"/></answer> 
        <id><xsl:value-of select="@answerid"/></id> 
        <value><xsl:value-of select="."/></value>   
</xsl:template>

<xsl:template match="result/*[not(@answerid)]">
         <answer><xsl:value-of select="local-name()"/></answer> 
        <value><xsl:value-of select="."/></value>  
</xsl:template>

哦,如果没有属性,他不需要一个空白节点..!+1 - Rookie Programmer Aravind

1

您缺少身份标识模板:

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

我已经更正了你的答案:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
  <xsl:template match="/XMLTest/result/*">
    <answer>
      <xsl:value-of select="local-name()"/>
    </answer>
    <id>
      <xsl:value-of select="@answerid"/>
    </id>
    <value>
      <xsl:value-of select="@*"/>
    </value>
  </xsl:template>


</xsl:stylesheet>

编辑1: 更新模板以丢弃属性为空的元素:在转换属性为元素之前,if条件检查属性是否为空。

  <xsl:template match="/XMLTest/result/*">
    <answer>
      <xsl:value-of select="local-name()"/>
    </answer>
    <xsl:if test="@answerid/.!=''">
      <id>
        <xsl:value-of select="@answerid"/>
     </id>
    </xsl:if>
    <xsl:if test="@*/.!=''">
    <value>
      <xsl:value-of select="@*"/>
    </value>
    </xsl:if>
  </xsl:template>

编辑2:在您早期的尝试中,您试图复制@*的值,@*表示任何名称的属性,因此它复制了@answerid的值(因为那是唯一可用的属性).. 你必须做的是.. value-of=".".. 请尝试下面的代码..

  <xsl:template match="/XMLTest/result/*">
    <answer>
      <xsl:value-of select="local-name()"/>
    </answer>
    <xsl:if test="@answerid/.!=''">
      <id>
        <xsl:value-of select="@answerid"/>
     </id>
    </xsl:if>
    <xsl:if test=".!=''">
    <value>
      <xsl:value-of select="."/>
    </value>
    </xsl:if>
  </xsl:template>

谢谢,这解决了我的问题!只有一个细节在代码中仍然不正确。如果子节点缺少answerid属性,则标签值不会被填充。我应该如何正确编写代码?我得到的结果是:<answer>QTXT1</answer><id/><value/>。 - Chrissy
很高兴知道..是什么?请继续。 - Rookie Programmer Aravind
@Chrissy,好的,那很容易,更新答案并检查一下。如果你需要其他帮助,请告诉我! - Rookie Programmer Aravind
现在我得到的是<answer>QTXT1</answer>,没有值,而不是<answer>QTXT1</answer><value>1</value>。所以某种程度上它仍然没有起作用? - Chrissy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接