使用布尔值来格式化XSLT中的字符串

时间:2012-11-26 21:19:44

标签: xslt boolean comma

我想用逗号分隔几个信息条目。但是,每个条目都可以为空,如果第一个出现的条目为空,则不应出现逗号。例如:

如果我们有四个XSLT参数:姓名,电话号码,地址,职业

我们有

  • 姓名:John
  • 电话号码:111-111-1111
  • 地址:Imaginary street
  • 职业:贝克

然后最后的字符串应该是:

John,111-111-1111,Imaginary street,Baker

如果名称和电话号码参数为空或为空,则最终字符串应为:

虚构的街道,贝克

如果只有电话号码为空或空,则最终字符串应为:

John,Imaginary street,Baker

在像C#这样的语言中,我会编写如下代码:

foreach (EntryObject entry in entryList)
{
    if (firstEntry == true && entry.Type != EntryType.Age && entry.Type != EntryType.Sex)
    {
        finalString += entry.ValueString;
        firstEntry = false;
    }
    else if (firstEntry == false && entry.Type != EntryType.Age && entry.Type != EntryType.Sex)
    { 
        finalString += ", " + entry.ValueString;
    }
}
return finalString;

但是,我听说XSLT中的变量是不可变的。我应该如何在XSLT中解决这个问题?

编辑: xml条目看起来像这样:

<AddressBook>
    <PersonalInfo>
        <Age>33</Age>
        <Sex>Male</Sex>
        <Name>John</Name>
        <PhoneNumber></PhoneNumber>
        <Address>Imaginary Street</Address>
        <Occupation>Baker</Occupation>
    </PersonalInfo>
</AddressBook>

请注意,某些条目可能为空,我只会使用姓名,电话号码,地址和职业。年龄和性别应该被忽略。

2 个答案:

答案 0 :(得分:2)

使用仅匹配非empy元素(string-length(.)>0或简称string(.))的XPath条件,然后使用position()函数检查元素是否是第一个元素。输入XML:

<root>
  <item>
    <name>John</name>
    <phoneNumber>111-111-1111</phoneNumber>
    <address>Imaginary street</address>
    <occupation>Baker</occupation>
  </item>
  <item>
    <name>Jane</name>
    <address>Another street</address>
    <occupation>Decorator</occupation>
  </item>
  <item>
    <address>Unknown</address>
  </item>
</root>

XSLT:

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

  <xsl:template match="item">
    <textItem>
      <xsl:for-each select="*[string(.)]">
        <xsl:if test="position()>1">
          <xsl:text>,</xsl:text>
        </xsl:if>
        <xsl:value-of select="."/>
      </xsl:for-each>
    </textItem>
  </xsl:template>

  <xsl:template match="text()">
  </xsl:template>

  <xsl:template match="root">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>

</xsl:stylesheet>

其中第一个模板是实际工作的模板,<xsl:template match="text()">删除不匹配元素中包含的文本(默认情况下,XSLT处理器会将此类文本复制到输出中),<xsl:template match="root">生成根元素输出文件。

结果:

<root>
  <textItem>John,111-111-1111,Imaginary street,Baker</textItem>
  <textItem>Jane,Another street,Decorator</textItem>
  <textItem>Unknown</textItem>
</root>

如果您只对某些字段感兴趣,可以使用union运算符(|)选择它们 - 例如如果您只想在上面的示例中使用电话,地址和职业,请将XSLT修改为:     

  <xsl:template match="item">
    <textItem>
      <xsl:for-each select="(phoneNumber|address|occupation)[string(.)]">
        <xsl:if test="position()>1">
          <xsl:text>,</xsl:text>
        </xsl:if>
        <xsl:value-of select="."/>
      </xsl:for-each>
    </textItem>
  </xsl:template>

  <xsl:template match="text()">
  </xsl:template>

  <xsl:template match="root">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:2)

以下是一个通用解决方案,它接受“黑名单”元素名称列表作为参数:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pIgnoreThese" select="' Age Sex '"/>

 <xsl:template match="PersonalInfo">
  <xsl:apply-templates select=
   "*[normalize-space()
    and
      not(contains($pIgnoreThese, concat(' ', name(), ' ')))
     ]"/>
   <xsl:text>&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="PersonalInfo/*">
  <xsl:if test="position() >1">, </xsl:if>
  <xsl:value-of select="."/>
 </xsl:template>
</xsl:stylesheet>

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

<AddressBook>
        <PersonalInfo>
            <Age>33</Age>
            <Sex>Male</Sex>
            <Name>John</Name>
            <PhoneNumber>111-111-1111</PhoneNumber>
            <Address>Imaginary Street</Address>
            <Occupation>Baker</Occupation>
        </PersonalInfo>
        <PersonalInfo>
            <Age>33</Age>
            <Sex>Male</Sex>
            <Name></Name>
            <PhoneNumber></PhoneNumber>
            <Address>Imaginary Street</Address>
            <Occupation>Baker</Occupation>
        </PersonalInfo>
        <PersonalInfo>
            <Age>33</Age>
            <Sex>Male</Sex>
            <Name>John</Name>
            <PhoneNumber></PhoneNumber>
            <Address>Imaginary Street</Address>
            <Occupation>Baker</Occupation>
        </PersonalInfo>
</AddressBook>

产生了想要的正确结果

John, 111-111-1111, Imaginary Street, Baker
Imaginary Street, Baker
John, Imaginary Street, Baker