如何仅在元素存在时在元素之间放置文本?

时间:2018-05-06 21:42:24

标签: xml xslt xslt-1.0

我只是在非常业余的级别编码,我最近进行了一个包含XML文件的大型项目。基本上我需要采用这些XML文件并以格式良好,可读的方式显示它们。我想为我拥有的所有XML文件编写一个XSLT文件。

每个XML文件都使用相同名称<datafield tag="650">的多个元素。 嵌套在这些元素中的是其他几个元素。始终会有<subfield code="a">。之后可能没有其他子字段,或者任何组合中可能有<subfield code="x"><subfield code="z"><subfield code"v">。我想在子字段之间添加连字符,但只有当这些子字段可见时才会显示。

例如我试过这个:

XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="so01.xsl"?>

<record>
    <datafield tag="650" ind1=" " ind2="0">
        <subfield code="a">Anthropology</subfield>
        <subfield code="z">Southwest, New</subfield>
        <subfield code="v">Periodicals.</subfield>
    </datafield>
    <datafield tag="650" ind1=" " ind2="0">
        <subfield code="a">Indians of North America</subfield>
        <subfield code="z">Southwest, New</subfield>
        <subfield code="v">Periodicals.</subfield>
    </datafield>
    <datafield tag="650" ind1=" " ind2="0">
        <subfield code="a">Archaeology</subfield>
        <subfield code="v">Periodicals.</subfield>
    </datafield>
    <datafield tag="650" ind1=" " ind2="7">
        <subfield code="a">Anthropology.</subfield>
    </datafield>
    <datafield tag="650" ind1=" " ind2="7">
        <subfield code="a">Antiquities.</subfield>
        <subfield code="x">History.</subfield>
    </datafield>
    <datafield tag="650" ind1=" " ind2="7">
        <subfield code="a">Archaeology.</subfield>
    </datafield>
    <datafield tag="650" ind1=" " ind2="7">
        <subfield code="a">Indians of North America.</subfield>
    </datafield>
</record>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html"/>
    <xsl:template match="/">
        <html>
        <body>
            <p>
                <xsl:for-each select="record/datafield[@tag='650']">&#160; &#160; &#160; &#160; &#160; &#160;
                    <xsl:value-of select="subfield[@code='a']"/>--<xsl:value-of select="subfield[@code='x']"/>--<xsl:value-of select="subfield[@code='z']"/>--<xsl:value-of select="subfield[@code='v']"/>
                </xsl:for-each>
            </p>
        </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

这种作品,但即使子字段不存在,它也会放置连字符,这会让读者感到困惑。

感谢您对此提供任何帮助,我非常感谢。我也完成了代码,这可能是(手指交叉)最后一步。然后我只需批量编辑XML文件以附加到XSL文件。

1 个答案:

答案 0 :(得分:1)

这种工作方式,但即使<subfield>不存在也会出现连字符 - 没有条件检查<subfield>元素是否具有特定值@code属性是否存在于输入XML中。 <{1}}之前的<xsl:if test="">条件会处理这种情况。

但是,编写XSLT代码以生成所需的HTML输出有不同的方法。当前的XSLT代码将生成一个<xsl:value-of>标记,其中包含来自<p>元素的所有值,我认为这些值不是所需的。我认为您需要一个与<subfield>相对应的单独<p>代码,且<datafield @tag='650'>子元素的hyphen分隔值。

为了实现此输出,模板需要更改如下。

<subfield>

这会生成一个HTML,如下所示

<xsl:template match="/">
    <html>
        <body>
            <xsl:for-each select="record/datafield[@tag='650']">
                <!-- create <p> tag for every <datafield> -->
                <p>
                    <!-- instead of hardcoding <subfield> elements, loop through
                         the available <subfield> element having @code attribute -->
                    <xsl:for-each select="subfield[@code]">
                        <xsl:value-of select="." />
                        <!-- if the position of the <subfield> is not last 
                             append hyphen characters to concatenated string -->
                        <xsl:if test="position() != last()">
                            <xsl:text>--</xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                </p>
            </xsl:for-each>
        </body>
    </html>
</xsl:template>

上面的XSLT代码只是实现输出的一种方法。可以使用不同的匹配模板而不是嵌套的<html> <body> <p>Anthropology--Southwest, New--Periodicals.</p> <p>Indians of North America--Southwest, New--Periodicals.</p> <p>Archaeology--Periodicals.</p> <p>Anthropology.</p> <p>Antiquities.--History.</p> <p>Archaeology.</p> <p>Indians of North America.</p> </body> </html> 或处理<xsl:for-each>的特定值的模板重新编写/修改相同的XSLT,即,如果仅考虑@code,则任何其他值被忽略了。