#xslt #xpath #xslt-1.0
#xslt #xpath #xslt-1.0
Вопрос:
Я пытаюсь заменить последнее вхождение символа ‘.’ символом ‘/’ при использовании XSLT (xslt 1.0 xsltproc). Как я могу это сделать?
Input.xml
<testng-results>
<suite>
<test>
<class name="system.apps.webdriver.tests.crm.mot.CreateTerritoryProposalTest">
<test-method status="PASS" started-at="2019-02-07T18:24:47Z" name="initTest">
</test-method>
<test-method status="FAIL" started-at="2019-02-07T18:24:47Z" name="ActListsForContactShowsContactRelatedTasksTest">
</test-method>
</class>
</test>
</suite>
</testng-results>
Текущий XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<Suite>
<xsl:for-each select="testng-results/suite/test/class/test-method">
<Test>
<Result_Path> <xsl:value-of select="concat('testngreports/', ../@name, '/', @name)"/> </Result_Path>
</Test>
</xsl:for-each>
</Suite>
</xsl:template>
</xsl:stylesheet>
Ожидаемый результат XML:
<?xml version="1.0" encoding="UTF-8"?>
<Suite>
<Test>
<Result_Path>testngreports/system.apps.webdriver.tests.crm.mot/CreateTerritoryProposalTest/initTest</Result_Path>
</Test>
<Test>
<Result_Path>testngreports/system.apps.webdriver.tests.crm.mot/CreateTerritoryProposalTest/ActListsForContactShowsContactRelatedTasksTest</Result_Path>
</Test>
</Suite>
Текущий выходной XML:
<?xml version="1.0" encoding="UTF-8"?>
<Suite>
<Test>
<Result_Path>testngreports/system.apps.webdriver.tests.crm.mot.CreateTerritoryProposalTest/initTest</Result_Path>
</Test>
<Test>
<Result_Path>testngreports/system.apps.webdriver.tests.crm.mot.CreateTerritoryProposalTest/ActListsForContactShowsContactRelatedTasksTest</Result_Path>
</Test>
</Suite>
Краткие сведения:
Текущий вывод:
testngreports/system.apps.webdriver.tests.crm.mot.CreateTerritoryProposalTest/initTest
Ожидаемый результат:
testngreports/system.apps.webdriver.tests.crm.mot/CreateTerritoryProposalTest/initTest
Последний символ ‘.’ должен быть заменен на ‘/’
Ответ №1:
С xsltproc
помощью — то libxslt
есть процессора — вы можете воспользоваться функцией str:tokenize()
расширения EXSLT и выполнить:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/testng-results">
<Suite>
<xsl:for-each select="suite/test/class">
<xsl:variable name="class-name">
<xsl:for-each select="str:tokenize(@name, '.')">
<xsl:value-of select="."/>
<xsl:choose>
<xsl:when test="position() >= last() - 1 ">/</xsl:when>
<xsl:otherwise>.</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="test-method">
<Test>
<Result_Path>
<xsl:text>testngreports/</xsl:text>
<xsl:value-of select="$class-name"/>
<xsl:value-of select="@name"/>
</Result_Path>
</Test>
</xsl:for-each>
</xsl:for-each>
</Suite>
</xsl:template>
</xsl:stylesheet>
Ответ №2:
Вероятно, требуется рекурсия. Напишите рекурсивный шаблон T: если предоставленная строка $S не содержит «.», то скопируйте ее без изменений; в противном случае пусть $L будет подстрокой до ($ S, «.»), а $ R будет подстрокой после ($ S, «.»). Если $ R содержит «.», то верните объединение $ L, «.» и результат рекурсивного вызова T, указав $ R в качестве параметра; в противном случае верните объединение $ L, «/» и $ R.