2013-10-07 6 views
0

У меня есть XML, который выглядит следующим образом. Он внешнее питание и не может быть изменен:Получение значения только одного узла-предка

<locations> 
    <country iso_code="CA"> 
    <name>Canada</name> 
    <state abbreviation="AB"> 
     <name>Alberta</name> 
     <city> 
     <name>Leduc</name> 
     <location id="1"/> 
     </city> 
    </state> 
    <state abbreviation="BC"> 
     <name>British Columbia</name> 
     <city> 
     <name>Abbotsford</name> 
     <location id="2"/> 
     <location id="3"/> 
     </city> 
    </state> 
    </country> 
    <country iso_code="US"> 
    <name>United States</name> 
    <state abbreviation="AZ"> 
     <name>Arizona</name> 
     <city> 
     <name >Wikiup</name> 
     <location id="1"/> 
     </city> 
    </state> 
    </country> 
</locations> 

Моя XSL выглядит следующим образом:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text" encoding="iso-8859-1"/> 
<xsl:strip-space elements="*" /> 
    <xsl:template match="/"> 
    <xsl:for-each select="//location[@id]"> 
     <xsl:call-template name="location"/> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template name="location"> 
    <xsl:value-of select="@id"/>, 
    <xsl:value-of select="ancestor::city[1]"/>, 
    <xsl:value-of select="ancestor::state[1]"/>, 
    <xsl:value-of select="ancestor::state[1]/@abbreviation"/>, 
    <xsl:value-of select="ancestor::country[1]"/>, 
    <xsl:value-of select="ancestor::country[1]/@iso_code"/>, 
    </xsl:template> 

</xsl:stylesheet> 

Когда я бегу xsltproc, я получаю этот выход (я вынул лишние строки, чтобы сделать его samller) :

1,Leduc,AlbertaLeduc,AB,CanadaAlbertaLeducBritish ColumbiaAbbotsford,CA, 
2,Abbotsford,British ColumbiaAbbotsford,BC,CanadaAlbertaLeducBritish ColumbiaAbbotsford,CA, 
3,Abbotsford,British ColumbiaAbbotsford,BC,CanadaAlbertaLeducBritish ColumbiaAbbotsford,CA, 
...etc... 

проблема заключается в том, когда я предок [1] ​​:: он подтягивает значения всех ancesotors, а не только тот, что я искал.

Вот что результат должен выглядеть следующим образом:

1,Leduc,Alberta,AB,Canada,CA, 
2,Abbotsford,British Columbia,BC,Canada,CA, 
3,Abbotsford,British Columbia,BC,Canada,CA, 
...etc... 

Я попытался с помощью ../../. нотация и получил тот же результат. Я играл с несколькими другими обозначениями, и это либо не работает, либо я снова получаю эти конкатенированные значения.

Как получить это значение только непосредственного родителя для обрабатываемого узла, а не всех из них на этом уровне?

Надеюсь, здесь я использую правильную терминологию. Это мое первое использование XSL для одного проекта.

Веб-ребята в магазине тоже в тупике. Они не используют XSL очень часто.

ответ

1

Если вы думаете о XML как о коробках, то <value-of> распаковывает выбранный флажок и все найденные в нем ящики, отбрасывает их и оставляет с фактическим содержимым, которое было в коробках. Это текстовые узлы. Атрибуты также выбрасываются, они являются ярлыками, наклеенными на коробку.

В случае <value-of select="ancestor::state">, распаковывает <state> коробку и находит две коробки внутри, <name> коробку и <city> коробку. Поскольку вы используете <strip-space elements="*">, он также выбрасывает всю «пузырчатую пленку» белого пространства, что и в противном случае. Он продолжает распаковываться и находит «Альберту» в поле <name>, а еще две коробки в поле <city>: A <name> и <location>.

А так игра продолжается: Внутри только распакованный <name> поле, он находит Leduc и сохраняет это право рядом Alberta, но он не находит ничего в <location> поле. Теперь больше нечего распаковывать. Таким образом, у нас осталась куча картона и отходов пузырьков, а фактическое содержание, которое составляет Alberta и Leduc (склеено вместе как AlbertaLeduc).

Вот предложено усовершенствование кода:

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

    <xsl:template match="/"> 
    <xsl:apply-templates select="//location[@id]"/> 
    </xsl:template> 

    <xsl:template match="location"> 
    <xsl:value-of select="@id"/>, 
    <xsl:value-of select="ancestor::city[1]/name"/>, 
    <xsl:value-of select="ancestor::state[1]/name"/>, 
    <xsl:value-of select="ancestor::state[1]/@abbreviation"/>, 
    <xsl:value-of select="ancestor::country[1]/name"/>, 
    <xsl:value-of select="ancestor::country[1]/@iso_code"/>, 
    </xsl:template> 

</xsl:stylesheet> 
+0

Благодарности нагрузки! Я сделал тот же код, что и ваше исправление, то есть: без шаблона, но это было всего лишь одним из моих трюков, прежде чем отправлять код, который у меня был в то время. Как я уже сказал, это одно, и я никогда не использую xsl. Отсутствующий кусок для меня был/name, чтобы добраться до значения узла! – user2855855

+0

Я рад, что это работает для вас! Если это ответит на ваш вопрос, не могли бы вы принять его, нажав галочку? –

Смежные вопросы