XSL转换子节点值的方式不同

时间:2012-11-24 20:42:50

标签: xml xslt-2.0

基本上,这是我正在尝试的逻辑。

对于父节点(ByFirstNameSearchList或ByLastNameSearchList):

-All子元素值为空(value1-4),插入值为% - 当一个或任何子元素具有值时,使用NOVAL替换所有具有空值的兄弟。

我有以下XML:

<GetName>
    <ByLastNameSearchList>
        <Value1/>
        <Value2/>
        <Value3/>
        <Value4/>
        <Value5/>
    </ByLastNameSearchList>
    <ByFirstNameSearchList>
        <Value1>String</Value1>
        <Value2>String</Value2>
        <Value3/>
        <Value4/>
        <Value5/>
    </ByFirstNameSearchList>
  </GetName>

这就是我想要的样子:

<GetName>
    <ByLastNameSearchList>
        <Value1>%</Value1>
        <Value2>%</Value2>
        <Value3>%</Value3>
        <Value4>%</Value4>
        <Value5>%</Value5>
    </ByLastNameSearchList>
    <ByFirstNameSearchList>
        <Value1>String</Value1>
        <Value2>String</Value2>
        <Value3>NOVAL</Value3>
        <Value4>NOVAL</Value4>
        <Value5>NOVAL</Value5>
    </ByFirstNameSearchList>
</GetName>

我真的很感谢你帮助我。相信我,我用我有限的XSL知识尝试了一切。

感谢。

2 个答案:

答案 0 :(得分:0)

此样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.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/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="ByFirstNameSearchList/* | ByLastNameSearchList/*">
      <xsl:copy>
         <xsl:choose>
            <xsl:when test="string-length(text()) gt 0">
               <xsl:value-of select="text()"/>
            </xsl:when>
            <xsl:when test="some $Value in ../* satisfies string-length($Value/text()) gt 0">
               <xsl:text>NOVAL</xsl:text>
            </xsl:when>
            <xsl:otherwise>
               <xsl:text>%</xsl:text>
            </xsl:otherwise>
         </xsl:choose>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

将产生您想要的输出。

更新:

这个版本更通用,因为它不依赖于只包含字符串的非空元素:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.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/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="ByFirstNameSearchList/* | ByLastNameSearchList/*">
      <xsl:choose>
         <xsl:when test="string-length(text()) gt 0">
            <xsl:copy-of select="."/>
         </xsl:when>
         <xsl:when test="some $Value in ../* satisfies string-length($Value/text()) gt 0">
            <xsl:copy>
               <xsl:text>NOVAL</xsl:text>
            </xsl:copy>
         </xsl:when>
         <xsl:otherwise>
            <xsl:copy>
               <xsl:text>%</xsl:text>
            </xsl:copy>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

就像这个一样简单(适用于XSLT 2.0和XSLT 1.0):

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

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

 <xsl:template match="/*/*/*[not(node())]">
  <xsl:copy>NOVAL</xsl:copy>
 </xsl:template>

 <xsl:template match="/*/*[not(*/node())]/*">
    <xsl:copy>%</xsl:copy>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<GetName>
    <ByLastNameSearchList>
        <Value1/>
        <Value2/>
        <Value3/>
        <Value4/>
        <Value5/>
    </ByLastNameSearchList>
    <ByFirstNameSearchList>
        <Value1>String</Value1>
        <Value2>String</Value2>
        <Value3/>
        <Value4/>
        <Value5/>
    </ByFirstNameSearchList>
</GetName>

产生了想要的正确结果:

<GetName>
      <ByLastNameSearchList>
            <Value1>%</Value1>
            <Value2>%</Value2>
            <Value3>%</Value3>
            <Value4>%</Value4>
            <Value5>%</Value5>
      </ByLastNameSearchList>
      <ByFirstNameSearchList>
            <Value1>String</Value1>
            <Value2>String</Value2>
            <Value3>NOVAL</Value3>
            <Value4>NOVAL</Value4>
            <Value5>NOVAL</Value5>
      </ByFirstNameSearchList>
</GetName>

<强>解释

  1. 身份规则“按原样”复制为其选择执行的每个节点。

  2. 模板会覆盖任何元素的标识模板,该元素是top元素的子元素,并且没有子元素。这将复制元素并生成一个文本节点子节点,其字符串值为字符串“NOVAL”。

  3. 第二个覆盖模板,它覆盖身份模板和第一个覆盖模板:匹配任何元素,该元素是top元素的子元素,其父元素没有包含子节点的子元素。这将复制元素并生成一个文本节点子节点,其字符串值为字符串“%”。

  4. 请注意

    1. 这是一种纯粹的“推动式”转型。

    2. 没有明确的条件说明(没有xsl:choose,没有xsl:when,没有xsl:otherwise),没有xsl:text甚至没有xsl:apply-templates(除了在身份模板中)。

    3. 没有使用特殊的XPath 2.0表达式(some ... satisfies ...),因为它们是不必要的。

    4. 未使用string-length()功能。