1

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

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

我们有

  • 姓名:约翰
  • 电话号码:111-111-1111
  • 地址:想象中的街道
  • 职业:贝克

那么最终的字符串应该是:

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

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

想象中的街道,贝克

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

约翰,想象中的街道,贝克

在像 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>

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

4

2 回答 2

2

使用仅匹配非空元素(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>

如果您只对某些字段感兴趣,您只需使用联合运算符 ( |) 选择它们 - 例如,如果您只想要上面示例中的电话、地址和职业,请将 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>
于 2012-11-26T21:31:32.227 回答
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
于 2012-11-27T04:59:03.877 回答