Равенство узлов XSLT, соответствующее всему - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть XML-файл вроде:

<?xml version="1.0" encoding="ISO-8859-1"?>
<list>
    <report file="onefile.xml" oneAttr="2123as"></report>
    <report file="myfile.xml" oneAttr="blabla"></report>
    <report file="myfile.xml" oneAttr="2123as"></report>
    <report file="another.xml" oneAttr="2123as"></report>
</list>     <!-- changed by edit -->

И мне нужна таблица стилей, которая может добавить новый элемент отчета после последнего совпадения @file="myfile.xml".

Что я получил до сих пор:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:template match="/list">
    <list>
    <xsl:variable name="insertAfter" select="report[@file='myfile.xml'][last()]"/>
    <xsl:for-each select="report">
        <xsl:copy-of select="."/>
        <xsl:text>&#xA;</xsl:text>
        <xsl:if test="current() = $insertAfter">
            <report file="newFile.xml"></report>
        </xsl:if>
        <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
    </list>
</xsl:template>

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

Я знаю, что в XSLT 2.0 есть этот оператор "eq", который, возможно, выполняет то, что я намереваюсь,но я бы хотел придерживаться XSLT 1.0.

Есть предложения по решению?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Этого можно добиться, используя функцию generate-id(...) , чтобы создать уникальный идентификатор узла last() и сопоставить его:

<xsl:template match="/list">
    <list>
    <xsl:variable name="insertAfter" select="generate-id(report[@file='myfile.xml'][last()])"/>
    <xsl:for-each select="report">
        <xsl:copy-of select="."/>
        <xsl:text>&#xA;</xsl:text>
        <xsl:if test="generate-id(current()) = $insertAfter">
            <report file="newFile.xml"></report>
        </xsl:if>
        <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
    </list>
</xsl:template>

Вывод:

<?xml version="1.0"?>
<list>
    <report file="onefile.xml" oneAttr="2123as"/>    
    <report file="myfile.xml" oneAttr="blabla"/>    
    <report file="myfile.xml" oneAttr="2123as"/>
    <report file="newFile.xml"/>
    <report file="another.xml" oneAttr="2123as"/>    
</list>
0 голосов
/ 27 сентября 2018

Ваше словесное описание 'последнее совпадение @ file = "myfile.xml" "переводится как

<xsl:template match="report[@file = 'myfile.xml'][last()]">
  <xsl:call-template name="identity"/>
  <report file="newFile.xml"></report>
</xsl:template>

, поэтому все, что вам нужно, это

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@* | node()" name="identity">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

    <xsl:template match="report[@file = 'myfile.xml'][last()]">
      <xsl:call-template name="identity"/>
      <report file="newFile.xml"></report>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / gWmuiJU

Проверка идентичности узла в XSLT 2 существует, но будет выполняться с оператором is, а не с eq.Но тебе все равно это не нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...