Как разместить текст между элементами только при наличии этих элементов? - PullRequest
0 голосов
/ 07 мая 2018

Я пишу код только на очень любительском уровне, и недавно я предпринял крупномасштабный проект с файлами XML. По сути, мне нужно взять эти XML-файлы и отобразить их в хорошо отформатированном и удобочитаемом виде. Я хотел бы написать один файл XSLT для всех имеющихся у меня файлов XML.

Каждый файл 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 голосов
/ 07 мая 2018

Этот тип работает, но он ставит дефисы, даже если <subfield> отсутствует - Нет условия для проверки, имеет ли элемент <subfield> конкретное значение в атрибуте @code присутствует во входном XML или нет. <xsl:if test=""> условие перед каждым <xsl:value-of> обработало бы этот случай.

Однако существуют разные способы написания XSLT-кода для генерации требуемого HTML-вывода. Текущий код XSLT создаст один тег <p>, содержащий все значения из элементов <subfield>, которые, я считаю, не являются необходимыми. Я думаю, что вам понадобится отдельный тег <p>, соответствующий каждому <datafield @tag='650'> и имеющий отдельное значение hyphen для дочерних элементов <subfield>.

Для достижения этого результата шаблон должен быть изменен, как показано ниже.

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

Это генерирует HTML, как показано ниже

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

Приведенный выше код XSLT является лишь одним из способов получения результата. Один и тот же XSLT может быть переписан / изменен с использованием различных подходящих шаблонов вместо вложенных <xsl:for-each> или шаблонов, обрабатывающих конкретные значения @code, т. Е. Если нужно учитывать только @code = 'a' or 'v' or 'x' or 'z', а любое другое значение игнорировать.

...