XSLT Преобразование нескольких файлов из подкаталога

114
8

Я создал файл XSLT, который может преобразовать один XML файл. Тем не менее, у меня есть несколько сотен каталогов с несколькими xml файлами. Есть ли способ в XSLT преобразовать все эти файлы. Я использую функцию коллекции, чтобы получить список всех файлов. Но, не уверен, как применить преобразование сейчас.


Вот мой пример XSLT файла. В принципе, я хочу просмотреть все XML файлы и применить таблицу шаблонов к отдельному файлу. Результат всех этих преобразований должен быть в одном плоском текстовом файле.


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

<xsl:output method="text" encoding="ISO-8859-1"/>
<xsl:template name="process">
<xsl:variable name="files" select="collection('file:///C:/files/testResults?select=*.xml;recurse=yes')"/>
<xsl:for-each select="$files">
<xsl:if test="(not(contains(document-uri(.), 'SuiteSetUp'))) and (not(contains(document-uri(.), 'SuiteTearDown')))">
<xsl:value-of select="tokenize(document-uri(.), '/')[last()]"></xsl:value-of>
<xsl:apply-templates select="/testResults/result/tables/table[14]">
<xsl:with-param name="title" select="/testResults/rootPath"></xsl:with-param>
</xsl:apply-templates>
<xsl:apply-templates select="/testResults/result/tables/table[15]"/>
</xsl:if>
</xsl:for-each>
</xsl:template>

<xsl:template match="table">
<xsl:param name="testName"></xsl:param>
<xsl:for-each select="row">
<xsl:if test="position() > 2">
<xsl:variable name="choices" select="col[2]"></xsl:variable>
<xsl:if test="contains($choices, 'fail')">
<xsl:value-of select="$testName"></xsl:value-of>
<xsl:text>|</xsl:text>
<xsl:value-of select="col[1]"></xsl:value-of>
<xsl:text>|</xsl:text>
<xsl:value-of select="foo:getCorrectChoices(col[2])"></xsl:value-of>
<xsl:text>|</xsl:text>
<xsl:value-of select="foo:getExpectedChoices(col[2])"></xsl:value-of>
<xsl:text>|</xsl:text>
<xsl:call-template name="NewLine"/>
</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:template>

<xsl:template name="NewLine">
<xsl:text>
</xsl:text>
</xsl:template>

<xsl:function name="foo:getCorrectChoices">
<xsl:param name="content"></xsl:param>
<xsl:analyze-string select="$content" regex="\[(\[.+?\])\] fail">
<xsl:matching-substring>
<xsl:value-of select="regex-group(1)"></xsl:value-of>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:function>
<xsl:function name="foo:getExpectedChoices">
<xsl:param name="content"></xsl:param>
<xsl:analyze-string select="$content" regex="fail\(expected \[(\[.+?\])\]">
<xsl:matching-substring>
<xsl:value-of select="regex-group(1)"></xsl:value-of>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:function>
</xsl:stylesheet>

спросил(а) 2011-05-25T21:43:00+04:00 9 лет, 5 месяцев назад
1
Решение
115

Вот, пожалуй, самый простой пример обработки всех xml файлов в поддереве файловой системы (с использованием функции collection(), реализованной в Саксоне):


<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

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

<xsl:template match="/">
<xsl:apply-templates mode="inFile" select=
"collection('file:///C:/temp?select=*.xml;recurse=yes')"/>
</xsl:template>
</xsl:stylesheet>


При применении к любому XML-документу (не используется, игнорируется) это преобразование применяет правило идентификации к каждому XML-документу, содержащемуся в любом из файлов *.xml в поддереве C:/Temp файловой системы.


Чтобы сделать больше ненужной обработки, нужно переопределить шаблон идентификации - в режиме inFile.


В вашем конкретном случае я считаю, что вы можете просто заменить:

            <xsl:apply-templates select="/testResults/result/tables/table[14]">     

с


            <xsl:apply-templates select="./testResults/result/tables/table[14]">    

и это применит желаемые шаблоны на узлах, выбранных из текущего (документа) node.

ответил(а) 2011-05-26T15:36:00+04:00 9 лет, 5 месяцев назад
41

Я просто хотел добавить легкую версию превосходного ответа Dimitre. Если у вас есть <foo> документы (root node), сидящие в каталоге, и работающая XSLT-программа для <foo>, просто создайте шаблон верхнего уровня следующим образом:


<xsl:template match="/">
<xsl:apply-templates select="collection($my_url)/foo"/>
</xsl:template>

Предположим, что вам нужен URL как параметр, <xsl:param name="my_url"/>, указанный в командной строке.

ответил(а) 2014-12-03T20:44:00+03:00 5 лет, 10 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема