XML и XSLT - отдельный узел включает запятые - PullRequest
1 голос
/ 28 июня 2019

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

<?xml version="1.0" encoding="UTF-8"?>
<fortnight>
    <hero>
        <name>Guardian</name>
        <characters>Bull,Knox,Penny</characters>
        <rarities>Rare,Epic,Legendary</rarities>
    </hero>

    <hero>
        <name>Deadly Blade</name>
        <characters>Crash,Scorpion</characters>
        <rarities>Epic,Legendary</rarities>
    </hero>

    <hero>
        <name>Enforcer</name>
        <characters>Grizzly</characters>
        <rarities>Uncommon,Rare,Epic,Legendary</rarities>
    </hero>
</fortnight>

и это мой XSLT-файл.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output omit-xml-declaration="yes" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:template match="/*">
        <characters>
            <xsl:apply-templates select="hero" />

            <xsl:value-of select="characters" />

        </characters>

    </xsl:template>

    <xsl:template match="text()" name="split">
        <xsl:param name="pText" select="."/>
        <xsl:if test="string-length($pText) >0">
            <character name="character">
                <xsl:value-of select=
      "substring-before(concat($pText, ','), ',')"/>
            </character>

            <xsl:call-template name="split">
                <xsl:with-param name="pText" select=
     "substring-after($pText, ',')"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Как я могу настроить мой XSLT для создания выходного файла только с узлом "символов", и если узел содержит запятые, он будет разделять их в выводе?

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Когда вы делаете <xsl:apply-templates select="hero" />, вы выбираете все дочерние элементы hero в fortnight, а затем XSLT ищет шаблоны для применения к ним.Тем не менее, в вашем XSLT нет шаблонов, соответствующих hero.Когда это происходит, применяются правила встроенного шаблона XSLT.В этом случае будет применяться следующий шаблон

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

Таким образом, по сути, он будет выбирать все в вашем XML, пока не дойдет до текстовых узлов.Не только текстовые узлы в characters, но и все текстовые узлы.

То, что вам нужно сделать, это настроить таргетинг только на те узлы, которые вы хотите разделить.Это означает замену <xsl:apply-templates select="hero" /> на <xsl:apply-templates select="hero/characters" />.

Также обратите внимание, что строку <xsl:value-of select="characters" /> можно удалить.Так как это в шаблоне, соответствующем fortnight, то будут выбраны только элементы characters, которые были прямым потомком fortnight, из которых нет ни одного.

0 голосов
/ 29 июня 2019

Хотя вы не показали нам желаемый результат преобразования, я считаю, это преобразование может быть полезным :

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

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

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

    <xsl:template match="characters/text()" name="split">
        <xsl:param name="pText" select="."/>
        <xsl:if test="string-length($pText) > 0">
            <character name="character">
                <xsl:value-of select=
                    "substring-before(concat($pText, ','), ',')"/>
            </character>

            <xsl:call-template name="split">
                <xsl:with-param name="pText" select=
                    "substring-after($pText, ',')"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Применительно к предоставленному исходному XML-документу :

<fortnight>
    <hero>
        <name>Guardian</name>
        <characters>Bull,Knox,Penny</characters>
        <rarities>Rare,Epic,Legendary</rarities>
    </hero>
    <hero>
        <name>Deadly Blade</name>
        <characters>Crash,Scorpion</characters>
        <rarities>Epic,Legendary</rarities>
    </hero>
    <hero>
        <name>Enforcer</name>
        <characters>Grizzly</characters>
        <rarities>Uncommon,Rare,Epic,Legendary</rarities>
    </hero>
</fortnight>

(наиболее вероятный) требуемый результат получен :

<characters>
   <character name="character">Bull</character>
   <character name="character">Knox</character>
   <character name="character">Penny</character>
   <character name="character">Crash</character>
   <character name="character">Scorpion</character>
   <character name="character">Grizzly</character>
</characters>
...