Несколько первоначальных вопросов о XPoc

Я работал с продуктом, который сразу же выводит «необработанный» системный журнал XML в собственный (но простой) формат XML, и нам нужно преобразовать часть информации в некоторых сообщениях.

Этот продукт поддерживает возможность настройки преобразования «необработанного» XML в форматы, адаптированные для продуктов SIEM, таких как Splunk и ArcSight, с использованием одного XSLT:

Продукт ==> «необработанный» вывод системного журнала XML ==> XSLT, специфичный для SIEM ==> SIEM (например, ArcSight, Splunk и т. д.)

Теперь у нас есть требование изменить ОДИН из элементов XML в некоторых необработанных сообщениях системного журнала, прежде чем сообщения будут преобразованы XSLT, «специфичным для SIEM». Итак, мы хотим иметь такой поток:

Продукт ==> «необработанный» вывод системного журнала XML ==> преобразованный «нашим XSLT» ==> преобразованный «XSLT, специфичным для SIEM, предоставленным поставщиком продукта» ==> SIEM (например, ArcSight, Splunk и т. д.)

Я работал над XSLT «нашего XSLT» (чтобы просто преобразовать этот один элемент, который затем будет передан в XSLT, специфичный для SIEM), и публиковал сообщения в одном из списков рассылки XSLT, и в одном из ответов я понял, кто-то упомянул о возможном использовании/использовании XProc для обеспечения «цепочки XSLT», поэтому я кое-что прочитал, но у меня все еще есть некоторые вопросы по поводу XProc...

а) Поскольку мы имеем дело с существующим продуктом в качестве источника XML системного журнала и поскольку нам необходимо использовать процессор XSLT, встроенный в продукт, который, по-видимому, использует XALAN-C v1, мы, к сожалению, ограничены используя XSLT 1.0.

Помешает ли это нам использовать XPoc?

б) Кроме того, я занимался разработкой XSLT в системе CENTOS и тестировал свой XSLT с помощью xsltproc, а затем, после того как я наладил работу с xsltproc, я тестировал XSLT с самим продуктом.

В рамках процесса разработки XSLT и обсуждений в списке рассылки XSLT я подтвердил, что механизм XSLT, используемый в продукте, — это XALAN-C, а также, что функция exslt:set-node() доступна и работает в как в xsltproc, так и в самом продукте.

Мое первоначальное намерение состояло в том, чтобы попытаться реализовать цепочку XSLT в нашем коде XSLT, но после некоторых исследований того, что будет задействовано, оказалось, что нам, по сути, придется как бы воспроизвести некоторые функции, которые уже предоставляются XProc, поэтому Я хочу попытаться использовать XProc для нашей работы, и я хочу попытаться заставить цепочку XSLT работать с XProc вместе с нашим XSLT и XSLT, предоставленным поставщиком продукта для SIEM.

Я публикую приведенную выше информацию, но я также хотел проверить, учитывая имеющиеся у нас ограничения (например, ограничение XSLT 1.0), есть ли какие-либо ошибки при использовании XProc для выполнения того, что я описал, в нашем случае?

в) Кроме того, я видел некоторые упоминания о Java... Если предположить, что продукт, с которым мы работаем, поддерживает XSLT 1.0, включая set-node(), понадобится ли Java для использования XProc в этом продукте?

Буду рад любым отзывам и заранее спасибо!

РЕДАКТИРОВАТЬ 1: Я как бы напутал в своем исходном посте в строке, где пытался показать «поток» XSLT... Пользовательский интерфейс SO заставлял часть текста исчезать. Сейчас я исправил эту строчку...

Обновлено еще раз: Я думаю, что мы близки к тому, что может работать с XSLT, опубликованным Коналом, но, судя по моим комментариям в ответ Коналу, я получаю эту ошибку:

It is an error to call 'apply-imports' when there's no current template rule.
error: file EmptyDetailsauditrecord.xml
xsltRunStylesheet : run failed

и я не понимаю, что вызывает эту ошибку... но у меня есть вопрос... с подходом, который предлагает Конал, требуется ли, чтобы XSLT " Third-party-stylesheet.xsl" был МОДИФИЦИРОВАН для добавления "режим" для всех шаблонов xsl:... ВНУТРИ "стороннего файла stylesheet.xsl"??? Кажется, ошибка говорит о том, что в импортированном XSLT нет совпадающих шаблонов, поэтому мне интересно, может быть, причина отсутствия совпадений заключается в том, что ни один из шаблонов xsl:template внутри «стороннего файла» stylesheet.xsl» имеет mode="pre-process" ???

РЕДАКТИРОВАТЬ 3:

Ниже приведен текущий файл конвейера.xsl после того, как я добавил код из своего XSLT в файл конвейера.xsl, а также добавил дополнительный режим="pre-process". Pipeline.xsl теперь запускается без ошибок, но по сути он принимает входной XML и преобразует его с помощью стороннего файла stylesheet.xsl вместо того, чтобы сначала выполнить преобразование, которое находится в самом конвейере.xsl, а затем выполнение стороннего файла stylesheet.xsl.

<?xml version = "1.0"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
      xmlns:exslt = "http://exslt.org/common"
      exclude-result-prefixes = "exslt"
      version = "1.0">

<xsl:import href = "./third-party-stylesheet.xsl"/>
<xsl:template mode = "pre-process" match = "/">
   <xsl:variable name = "pre-processed-xml">
      <xsl:apply-templates mode = "pre-process" select = "/" />
   </xsl:variable>

   <xsl:message><xsl:value-of select = "$pre-processed-xml"/></xsl:message>
   <xsl:for-each select = "exslt:node-set($pre-processed-xml)">
      <!-- apply the imported templates to the pre-processed-xml -->
      <xsl:apply-imports/>
   </xsl:for-each>
</xsl:template>

<!-- pre-processor generally copies the input -->
<xsl:template match = "@*|node()" mode = "pre-process">
  <xsl:copy>
    <xsl:apply-templates mode = "pre-process" select = "@*|node()"/>
  </xsl:copy>
</xsl:template>




    <!-- THE CODE BELOW IS WHAT WAS ORIGINALLY IN  "my XSLT" -->


    <!-- Handle processing of <ExtraDetails>... -->
    <xsl:template match = "/syslog/audit_record/ExtraDetails">


    <!-- SET GLOBAL VARIABLE $incomingMessageID... -->
    <xsl:variable name = "incomingMessageID" select = "/syslog/audit_record/MessageID"/>

    <!-- SET GLOBAL VARIABLE $incomingExtraDetails... -->
    <xsl:variable name = "incomingExtraDetails" select = "/syslog/audit_record/ExtraDetails"/>



        <xsl:message>+++++++++ UPON ENTERING template match - incomingExtraDetails: [<xsl:value-of select = "$incomingExtraDetails"/>]</xsl:message>
        <ExtraDetails>

.
.
.
.
        </ExtraDetails>

    </xsl:template>






</xsl:stylesheet>

РЕДАКТИРОВАТЬ 4A: Первый запуск XSLT (initialparsetestSMALL.xsl):

      <?xml version = "1.0"?>
      <xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
      xmlns:exslt = "http://exslt.org/common"
      exclude-result-prefixes = "exslt"
      version = "1.0">

    <!-- SET GLOBAL VARIABLE $incomingMessageID... -->
    <xsl:variable name = "incomingMessageID" select = "/syslog/audit_record/MessageID"/>

    <!-- SET GLOBAL VARIABLE $incomingExtraDetails... -->
    <xsl:variable name = "incomingExtraDetails" select = "/syslog/audit_record/ExtraDetails"/>



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



    <!-- Handle processing of <ExtraDetails>... -->
    <xsl:template match = "/syslog/audit_record/ExtraDetails">
        <ExtraDetails>
            <xsl:choose>
                <xsl:when test = "$incomingMessageID  = '412'">

                    <xsl:variable name = "before-tab" select = " substring-before( substring-after($incomingExtraDetails, '='), '[Tab]' ) "/>
                    <xsl:variable name = "after-tab" select = " substring-before( substring-after($incomingExtraDetails, '[Tab]'), ';') "/>
                    <xsl:variable name = "front" select = " substring-before($incomingExtraDetails, '=')"/>
                    <xsl:variable name = "frontEqual" select = "concat($front, '=')"/>
                    <xsl:variable name = "back" select = " substring-after($incomingExtraDetails, ';')"/>
                    <xsl:variable name = "redacted" select = "'************;'"/>
                    <xsl:variable name = "newExtraDetails" select = "concat($frontEqual,$redacted)"/>
                    <xsl:variable name = "newExtraDetailsAll" select = "concat($newExtraDetails,$back)"/>

                    <xsl:value-of select = "$newExtraDetailsAll"/>
                </xsl:when>


                <xsl:otherwise>
                    <xsl:choose>
                        <xsl:when test = "$incomingExtraDetails = ''">
                            <xsl:message>+++++++++++++++++++++++++++++ incomingExtraDetails is null</xsl:message>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:message>+++++++++++++++++++++++++++++++++++++ NOT 412</xsl:message>
                            <xsl:value-of select = "$incomingExtraDetails"/>
                            <xsl:message>+++++++++++++++++++++++++++++++++++++ DONE NOT 412</xsl:message>
                        </xsl:otherwise>
                    </xsl:choose>

                </xsl:otherwise>

            </xsl:choose>

        </ExtraDetails>

    </xsl:template>

</xsl:stylesheet>

РЕДАКТИРОВАТЬ 4B: второй/последний XSLT для запуска (сторонний-stylesheet.xsl) - обратите внимание, что этот XSLT производит текстовый вывод:

<?xml version = "1.0"?>
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
    <xsl:import href='./RFC5424Changes.xsl'/>
    <xsl:output method='text' version='1.0' encoding='UTF-8'/>
    <xsl:key name = "CAProperty_Name" match = "CAProperty" use = "@Name"/>
    <xsl:template match = "/">
        <xsl:apply-imports/>
        <xsl:for-each select = "syslog/audit_record"><xsl:if test = "not(key('CAProperty_Name','KeyDescription')) and not(key('CAProperty_Name','ApplicationObjectID')) and (Action = 'Retrieve password' or Action = 'Use Password' or Action = 'Retrieve SSH Key' or Action = 'CPM Change Password' or Action = 'CPM Reconcile Password')">|<xsl:value-of select = "Issuer"/>|<xsl:value-of select = "IsoTimestamp"/>|<xsl:value-of select = "Action"/>|<xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'UserName'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'Address'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'PolicyID'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'DeviceType'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'Database'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'AWSAccountID'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'AWSAccessKeyID'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'ActiveDirectoryID'" /></xsl:call-template>
            </xsl:if>
        </xsl:for-each>

        <xsl:for-each select = "syslog/audit_record"><xsl:if test = "Action = 'Logon' or Action = 'User Authentication'">|<xsl:value-of select = "Issuer"/>|<xsl:value-of select = "IsoTimestamp"/>|<xsl:value-of select = "Action"/>|<xsl:value-of select = "Station"/>|</xsl:if>
        </xsl:for-each>

        <xsl:for-each select = "syslog/audit_record"><xsl:if test = "Action = 'Store password' or Action = 'Store SSH Key'">|<xsl:value-of select = "IsoTimestamp"/>|<xsl:value-of select = "Action"/>|<xsl:value-of select = "Safe"/>|<xsl:value-of select = "File"/>|</xsl:if>
        </xsl:for-each>

            <!-- MessageID = '361' is Command Audit                     -->
            <!-- MessageID = '359' is Command Audit                     -->
            <!-- MessageID = '302' is Disconnect Audit  -->
        <xsl:for-each select = "syslog/audit_record"><xsl:if test = "MessageID = '361' or MessageID = '359' or MessageID = '411' or MessageID = '412' or MessageID = '436' or MessageID = '300' or MessageID = '302'">|<xsl:value-of select = "Issuer"/>|<xsl:value-of select = "IsoTimestamp"/>|<xsl:value-of select = "MessageID"/>|<xsl:value-of select = "Action"/>|<xsl:value-of select = "Station"/>|<xsl:value-of select = "File"/>|<xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'PolicyID'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'Address'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'DeviceType'" /></xsl:call-template><xsl:call-template name = "print-file-category"><xsl:with-param name = "category-name" select = "'Database'" /></xsl:call-template><xsl:value-of select = "ExtraDetails"/>|</xsl:if>
        </xsl:for-each>

            <!-- MessageID = '471' is Access Succeeded Syslog -->
        <xsl:for-each select = "syslog/audit_record"><xsl:if test = "MessageID = '471'">|<xsl:value-of select = "IsoTimestamp"/>|<xsl:value-of select = "MessageID"/>|<xsl:value-of select = "Issuer"/>|<xsl:value-of select = "Action"/>|<xsl:value-of select = "Station"/>|<xsl:value-of select = "ExtraDetails"/>|</xsl:if>
        </xsl:for-each>
    </xsl:template>

    <!-- replace all occurences of the character(s) `from'
         by the string `to' in the string `string'.-->
    <xsl:template name = "string-replace" >
        <xsl:param name = "string"/>
        <xsl:param name = "from"/>
        <xsl:param name = "to"/>
        <xsl:choose>
            <xsl:when test = "contains($string,$from)">
                <xsl:value-of select = "substring-before($string,$from)"/>
                <xsl:value-of select = "$to"/>
                <xsl:call-template name = "string-replace">
                    <xsl:with-param name = "string" select = "substring-after($string,$from)"/>
                    <xsl:with-param name = "from" select = "$from"/>
                    <xsl:with-param name = "to" select = "$to"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select = "$string"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name = "print-file-category">
        <xsl:param name = "category-name"/>
        <xsl:param name = "print-pipe-if-empty" select = "true()"/>
        <xsl:variable name = "out">
            <xsl:for-each select = "CAProperties/CAProperty">
                <xsl:choose>
                    <xsl:when test = "@Name=$category-name">
                        <xsl:value-of select = "@Value" />
                    </xsl:when>
                </xsl:choose>
            </xsl:for-each>
        </xsl:variable>
        <xsl:value-of select = "$out" />
        <xsl:choose>
            <xsl:when test = "$print-pipe-if-empty and $out=''">|</xsl:when>
            <xsl:when test = "$out!=''">|</xsl:when>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

РЕДАКТИРОВАТЬ 4C: Пример ввода XML (sample-syslog-message.xml):

<?xml version = "1.0" encoding = "UTF-8"?>
<syslog>

  <audit_record>
    <Rfc>yes</Rfc>
    <Timestamp>Jul 21 01:10:30</Timestamp>
    <IsoTimestamp>2024-07-21T01:10:30Z</IsoTimestamp>
    <Hostname>VAU01</Hostname>
    <Vendor>Test</Vendor>
    <Product>Vau</Product>
    <Version>14.0.0000</Version>
    <MessageID>412</MessageID>
    <Desc>logging</Desc>
    <Severity>Info</Severity>
    <Issuer>xxxxx</Issuer>
    <Action>logging</Action>
    <SourceUser/>
    <TargetUser/>
    <File>Root\Operating</File>
    <Station>xx.yy.4.8</Station>
    <Location/>
    <Category/>
    <RequestId/>
    <Reason/>
    <ExtraDetails>Command=11111[Tab]11111;ConnectionComponentId=Users;9T;</ExtraDetails>
    <GatewayStation/>
    <CAProperties>
      <CAProperty Name = "PolicyID" Value = "Windows"/>
      <CAProperty Name = "UserName" Value = "xxxxx"/>
      <CAProperty Name = "Address" Value = "my.solutions"/>
      <CAProperty Name = "DeviceType" Value = "Operating System"/>
      <CAProperty Name = "Disabled" Value = "No Reason"/>
      <CAProperty Name = "Logon" Value = "my"/>
      <CAProperty Name = "CreationMethod" Value = "VWA"/>
    </CAProperties>
  </audit_record>

</syslog>

РЕДАКТИРОВАТЬ 4D: небольшой сценарий оболочки для последовательного запуска XSLT (Linux):

#!/bin/bash

xsltproc -o outfromstep1 initialparsetestSMALL.xsl sample-syslog-message.xml && cat outfromstep1

xsltproc -o outfromstep2 third-party-stylesheet.xsl outfromstep1 && cat outfromstep2

РЕДАКТИРОВАТЬ 4E: Пример вывода запуска (из стороннего файла stylesheet.xsl):

[root@nodejs stackoverflowexample]# ./runXslt.sh
<?xml version = "1.0"?>
<syslog>

  <audit_record>
    <Rfc>yes</Rfc>
    <Timestamp>Jul 21 01:10:30</Timestamp>
    <IsoTimestamp>2024-07-21T01:10:30Z</IsoTimestamp>
    <Hostname>VAU01</Hostname>
    <Vendor>Test</Vendor>
    <Product>Vau</Product>
    <Version>14.0.0000</Version>
    <MessageID>412</MessageID>
    <Desc>logging</Desc>
    <Severity>Info</Severity>
    <Issuer>xxxxx</Issuer>
    <Action>logging</Action>
    <SourceUser/>
    <TargetUser/>
    <File>Root\Operating</File>
    <Station>xx.yy.4.8</Station>
    <Location/>
    <Category/>
    <RequestId/>
    <Reason/>
    <ExtraDetails>Command=************;ConnectionComponentId=Users;9T;</ExtraDetails>
    <GatewayStation/>
    <CAProperties>
      <CAProperty Name = "PolicyID" Value = "Windows"/>
      <CAProperty Name = "UserName" Value = "xxxxx"/>
      <CAProperty Name = "Address" Value = "my.solutions"/>
      <CAProperty Name = "DeviceType" Value = "Operating System"/>
      <CAProperty Name = "Disabled" Value = "No Reason"/>
      <CAProperty Name = "Logon" Value = "my"/>
      <CAProperty Name = "CreationMethod" Value = "VWA"/>
    </CAProperties>
  </audit_record>

</syslog>
|xxxxx|2024-07-21T01:10:30Z|412|logging|xx.yy.4.8|Root\Operating|Windows|my.solutions|Operating System||Command=************;ConnectionComponentId=Users;9T;|

Напоминание: моя цель — реализовать XSLT (который будет принимать входные данные XML для каждого образца и вызывать первое преобразование для этого входящего XML, а затем выполнять второе преобразование для выходных данных первого преобразования.

Как обсуждалось, в идеале мы не можем изменить второй XSLT (сторонний файл stylesheet.xsl, поскольку это не «наше программное обеспечение»).

РЕДАКТИРОВАТЬ 5:

Изначально я не включил файл «pipeline2.xsl», в котором есть код, опубликованный Коналом, а также код XSLT для выполнения «предварительной обработки», но у меня возникла проблема, потому что когда я тестирую этот «pipeline2. xsl», он ВСЕ ЕЩЕ по сути пропускает обработку XSLT предварительной обработки, встроенного в «pipeline2.xsl», поэтому я публикую фрагмент Pipeline2.xsl в надежде, что кто-нибудь сможет сказать мне, почему это происходит?

Вот фрагмент:

<?xml version = "1.0"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
      xmlns:exslt = "http://exslt.org/common"
      exclude-result-prefixes = "exslt"
      version = "1.0">

<xsl:import href = "./third-party-stylesheet.xsl"/>
<xsl:template mode = "pre-process" match = "/">
   <xsl:variable name = "pre-processed-xml">
      <xsl:apply-templates mode = "pre-process" select = "/" />
   </xsl:variable>

   <xsl:message><xsl:value-of select = "$pre-processed-xml"/></xsl:message>
   <xsl:for-each select = "exslt:node-set($pre-processed-xml)">
      <!-- apply the imported templates to the pre-processed-xml -->
      <xsl:apply-imports/>
   </xsl:for-each>
</xsl:template>

<!-- pre-processor generally copies the input -->
<xsl:template match = "@*|node()" mode = "pre-process">
  <xsl:copy>
    <xsl:apply-templates select = "@*|node()"/>
  </xsl:copy>
</xsl:template>


<!-- pre-processor should e.g. remove a particular element -->
<!-- <xsl:template match = "unwanted-element" mode = "pre-process"/> -->




<!-- From Conal's posts, I interpreted that he intended that, by the 2 lines above here, that I should basically add the code from my     initialparsetest.xsl below here, i.e., the initial transformation of the <ExtraDetails>
element is performed in this pipeline XSLT and then after that the code above would cause the transformation in the third-party-stylesheet.xsl to be performed -->


<!-- BUT when I test, the code below (the xsl:template...) does NOT SEEM to be being executed !! -->




    <!-- Handle processing of <ExtraDetails>... -->
    <xsl:template mode = "pre-process" match = "/syslog/audit_record/ExtraDetails">


    <!-- SET GLOBAL VARIABLE $incomingMessageID... -->
    <xsl:variable name = "incomingMessageID" select = "/syslog/audit_record/MessageID"/>

    <!-- SET GLOBAL VARIABLE $incomingExtraDetails... -->
    <xsl:variable name = "incomingExtraDetails" select = "/syslog/audit_record/ExtraDetails"/>


        <xsl:message>+++++++++ UPON ENTERING template match - incomingExtraDetails: [<xsl:value-of select = "$incomingExtraDetails"/>]</xsl:message>
        <ExtraDetails>
            <xsl:choose>
                <!-- START 'when' TO HANDLE '412' requests -->
                <xsl:when test = "$incomingMessageID  = '412'">
                    <xsl:message>+++++++++++++++++++++++++++++++++++++ Processing a request with MessageId 412</xsl:message>
                    <xsl:message> VARIABLE incomingExtraDetails=[<xsl:value-of select = "$incomingExtraDetails"/>] </xsl:message>


.
.
.
.
BUNCH OF CODE 
.
.
.

        </ExtraDetails>

    </xsl:template>



</xsl:stylesheet>

Я также нашел эту тему SO:

Сопоставление шаблона XSLT с установленным атрибутом режима не работает

который, похоже, имеет схожие симптомы (XSLT с режимом, который не выполняется), поэтому мне интересно, может быть, проблема, которую я вижу в моем конвейере2.xsl, вызвана той же самой вещью (отсутствием шаблонов применения?) ?

Если да, то что мне нужно добавить в файл Pipeline2.xsl, чтобы он начал работать?

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

michael.hor257k 09.08.2024 07:21

michael.hor257k - Я согласен - как я уже говорил, предлагалось попробовать XProc, но я никогда о нем не слышал, и я пытался понять XProc, чтобы оценить, будет ли он жизнеспособным, но мы, вероятно, не сможем развертывать в продукте любой код Java или C, поэтому кажется, что я возвращаюсь к подходу «использовать XSLT 1.0». Спасибо!

user555303 09.08.2024 13:46

Я до сих пор не понимаю, почему вы не можете просто изменить существующую таблицу стилей XSLT, чтобы она обрабатывала необработанный XML в нужный результат за один проход. При необходимости опубликуйте новый вопрос, указав все 3.

michael.hor257k 09.08.2024 14:52

michael.hor257k — причина, по которой мы не ХОТИМ делать все в одном XSLT, заключается в том, что XSLT, специфичные для SIEM, предоставляются НАМ поставщиком продукта, и поэтому мы не хотим изменять XSLT, специфичные для SIEM. . Итак, мы хотим как бы разделить изменения, которые вносит «наш XSLT» (до того, как будет обработан XSLT, специфичный для SIEM). Таким образом, ответ заключается в том, что мы не можем сделать один XSLT не по технической причине, а скорее по причине своего рода деловая причина.

user555303 09.08.2024 15:30

Вы можете написать свою собственную таблицу стилей и включить/импортировать существующую. Но более подробный ответ невозможен без минимально воспроизводимого примера (как вы также узнаете ниже).

michael.hor257k 09.08.2024 15:56

Пожалуйста, отредактируйте свой вопрос и покажите (1) необработанный вывод XML из вашей системы, (2) исходную таблицу стилей XSLT, предоставленную вам поставщиком, и (3) точный результат, который вы ожидаете получить.

michael.hor257k 09.08.2024 19:27

К вашему сведению, я добавлю пример двух XSLT, которые мне нужно запустить последовательно, а также образец запроса/XML через несколько минут. Извините, потребовалось время, чтобы собрать это воедино.

user555303 09.08.2024 20:46

ок, обновил ОП новыми файлами!

user555303 09.08.2024 21:22

Обратите внимание: ваш код все еще не является минимальной воспроизводимой формой. В одном из файлов с самого начала немного не хватает строк, а из другого вырезан кусок строк и заменен на «КУЧКА КОДА». Суть воспроизводимого примера в том, что люди здесь действительно могут взять ваш XSLT-код и запустить его, настроить и т. д. Если это даже не правильно сформированный XML, то, откровенно говоря, вы зря тратите время людей. Мы не хотим видеть весь ваш код: вы можете сократить его до образца, но он должен быть работоспособным, и вы должны проверить, что он работает.

Conal Tuohy 10.08.2024 06:30

кроме последнего файла (pipeline2.xsl), все остальные файлы должны быть работоспособными... Когда я собрал все остальные вместе, я запустил их здесь, прежде чем добавить их в OP. Как вы думаете, какого файла «немного не хватает»??

user555303 10.08.2024 06:35

ре. тот, что с кучей кода - мне нужно подумать об этом, чтобы увидеть, что я могу предоставить, достаточное для всех вас. Кстати, @Conal, что Pipeline2.xsl - это, по сути, второй пример кода, который вы опубликовали... Я знаю, что вы хотите большего, но можете ли вы быстро взглянуть на него? Кроме того, в конце вашего примера было две строки, и я «предполагал», что вы имели в виду, что я должен поместить ТАМ свой код предварительной обработки (который не запускается). Было ли мое предположение верным?

user555303 10.08.2024 06:36

Неработающие — это ваши правки, помеченные 4A и 5. А в другом блоке кода сверху и снизу есть лишние не-XML-коды, но, по крайней мере, там очевидно, что не так.

Conal Tuohy 10.08.2024 06:40

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

Conal Tuohy 10.08.2024 08:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
13
85
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обратите внимание: теперь, когда вопрос стал немного яснее, я решил в интересах ясности удалить свой первоначальный ответ и начать с нуля.

Цель состоит в том, чтобы создать конвейер, который последовательно запускает две таблицы стилей XSLT; во-первых, pre-processor.xsl, который мы определяем сами, чья роль заключается в внесении некоторых изменений во входные данные, прежде чем они будут обработаны third-party-stylesheet.xsl, содержимое которого мы не хотим менять.

Итак, у нас есть три файла XSLT; два упомянутых выше, и основная таблица стилей pipeline.xsl, задача которой — запуск двух других.

pipeline.xsl:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
      xmlns:exslt = "http://exslt.org/common"
      exclude-result-prefixes = "exslt"
      version = "1.0">

<xsl:import href = "third-party-stylesheet.xsl"/>
<xsl:import href = "pre-processor.xsl"/>

<xsl:output method = "text"/>

<xsl:template match = "/">
    <xsl:param name = "run-preprocessor" select = " 'yes' "/>
    <xsl:choose>
        <xsl:when test = "$run-preprocessor = 'yes' ">
            <xsl:variable name = "pre-processed-xml">
                <xsl:apply-templates mode = "pre-process" select = "/"/>
            </xsl:variable>
            <xsl:apply-templates select = "exslt:node-set($pre-processed-xml)">
                <xsl:with-param name = "run-preprocessor" select = " 'no' "/>
                <!-- 👇 recurses, but effectively calls the code below -->
            </xsl:apply-templates>
        </xsl:when>
        <xsl:otherwise>
            <!-- effectively called from ☝️ above -->
            <xsl:apply-imports/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

pipeline.xsl импортирует две другие таблицы стилей, чтобы применить шаблоны из обеих.

Сначала он запускает pre-processor.xsl (который написан в режиме pre-process, чтобы его шаблоны не конфликтовали с шаблонами third-party-stylesheet.xsl).

Вывод pre-processor.xsl фиксируется в переменной, которая представляет собой «фрагмент дерева результатов» (поскольку это XSLT 1.0), поэтому нам нужно использовать функцию exslt:node-set(), чтобы преобразовать его обратно в документ, к которому мы затем можем применить шаблоны third-party-stylesheet.xsl чтобы.

Единственная сложность здесь заключается в том, как, когда мы снова вызываем apply-templates, мы получаем шаблон match = "/" в third-party-stylesheet.xsl, соответствующий нашему предварительно обработанному документу, вместо того, чтобы он соответствовал шаблону match = "/" в pipeline.xsl и повторял бесконечную рекурсию. Хитрость заключается в том, чтобы использовать параметр, указывающий, завершен ли этап предварительной обработки. Когда мы делаем рекурсивный вызов apply-templates с нашим предварительно обработанным документом, мы передаем флаг соответствующему шаблону, сообщающий, что предварительная обработка завершена. Если наш шаблон получит этот флаг, он сможет использовать оператор apply-imports для перехода к шаблону в импортированном third-party-stylesheet.xsl.

Обратите внимание: third-party-stylesheet.xsl использует метод вывода text, как и наш pipeline.xsl.

Вот другие мои файлы: pre-processor.xsl:

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

<!-- pre-processor generally copies the input -->
<xsl:template match = "@*|node()" mode = "pre-process">
  <xsl:copy>
    <xsl:apply-templates select = "@*|node()" mode = "pre-process"/>
  </xsl:copy>
</xsl:template>

<!-- pre-processor should e.g. remove a particular element -->
<xsl:template match = "unwanted-element" mode = "pre-process"/>

</xsl:stylesheet>

third-party-stylesheet.xsl:

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

   <xsl:output method = "text"/>

   <xsl:template match = "/">
      <xsl:value-of select = "."/>
   </xsl:template>

</xsl:stylesheet>

input.xml:

<example>
    <desired-text>This text should make it past the pre-processor</desired-text>
    <unwanted-element>This element should be filtered out by the pre-processor</unwanted-element>
    <desired-text>This should appear</desired-text>
    <unwanted-element>This should not appear</unwanted-element>
</example>

Запуск xsltproc -o output.txt pipeline.xsl input.xml производит:

output.txt:


    This text should make it past the pre-processor
    
    This should appear
    

Конал Туохи. Я внес некоторые изменения в исходное сообщение, чтобы исправить некоторые проблемы, приводившие к отсутствию строк. К вашему сведению, в «желаемом потоке» нам нужно только ДВА XSLT: (а) мой XSLT, который преобразуется в элементе, после чего мы хотим передать этот измененный XML в XSLT, специфичный для SIEM. Я пытался настроить опубликованный вами XSLT, но мне кажется, что в опубликованном вами XSLT были некоторые опечатки, плюс то, что вы опубликовали, ожидало 4 XSLT (вместо 2), и у меня возникли проблемы с корректировкой опубликованного вами XSLT. Итак, после этого я опубликую отредактированную версию вашего XSLT. Не могли бы вы просмотреть и исправить то, что я публикую?

user555303 09.08.2024 13:43

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

Conal Tuohy 09.08.2024 13:51

Конал - да, это правильно - спасибо - к вашему сведению - я пытался настроить то, что вы изначально опубликовали - следует ли мне опубликовать то, что у меня есть (но все еще появляется ошибка "ошибка времени выполнения: файл конвейер.xsl, строка 27, элемент apply-imports" Вызов «apply-imports», когда нет текущего правила шаблона, является ошибкой».? Или мне просто подождать вашего обновления и попробовать обновленный конвейер XSLT?

user555303 09.08.2024 14:11

ок, нвм, дай мне попробовать твой новый XSLT

user555303 09.08.2024 14:12

Конал Туохи. Я не уверен, что SO удаляет его, но я думаю, что в строке 4 в новом XSLT, который вы опубликовали, отсутствует конечная косая черта. Я исправил это, но когда я запускаю ваш XSLT (я назвал «pipeline2.xsl»), я получаю ошибку: [root@nodejs stackoverflow1]# xsltproc -o foo pipeline2.xsl EmptyDetailsauditrecord.xml && cat foo runtime error: file pipeline2.xsl line 14 element apply-imports It is an error to call 'apply-imports' when there's no current template rule.

user555303 09.08.2024 14:22

Конал Туохи: Если вы модифицировали XSLT, где он выполняет то, что вы называли «препроцессором XSLT» (то, что я назвал «нашим XSLT» в своем исходном посте)? Похоже, что ваш модифицированный XSLT не вызывает обработку XSLT «нашего XSLT» (до того, как он запустит сторонний файл stylesheet.xsl)?

user555303 09.08.2024 14:45

Конал Туохи - Ааа - я пересматривал ваш обновленный XSLT и, кажется, не понимал, что должен делать опубликованный вами XSLT... Я думаю, что в строках в конце вашего XSLT: ` <!- - препроцессор обычно копирует ввод --> <xsl:template match = "@*|node()" mode = "pre-process"> <xsl:copy> <xsl:apply-templates select = "@*| node()"/> </xsl:copy> </xsl:template> <!-- препроцессор должен, например. удалить определенный элемент --> <xsl:template match = "unwanted-element" mode = "pre-process"/> ` вы ожидали, что этот код будет включать в себя то, что у меня было в моем «нашем XLST»?

user555303 09.08.2024 15:04

Конал. Однако теперь, когда я это понимаю, я до сих пор не знаю, почему я получаю сообщение об ошибке «apply-imports». Вызов «apply-imports» является ошибкой, когда нет текущего правила шаблона. `

user555303 09.08.2024 15:05

возможно, если бы вы опубликовали пример вашего исходного XML и имеющегося у вас XSLT, включая изменения, которые вы хотите, чтобы ваш препроцессор внес, можно было бы попытаться воспроизвести проблему. Без этого мой ответ, естественно, будет несколько гипотетичным и уклончивым. Всегда полезно опубликовать stackoverflow.com/help/minimal-reproducible-example

Conal Tuohy 09.08.2024 15:45

@ConalTuohy - Я думаю, вы хотите добавить mode = "pre-process" к xsl:apply-templates в преобразовании личности.

Daniel Haley 09.08.2024 16:12

На самом деле, я как раз собирался опубликовать, но что-то другое, чем то, что написал Дэниел. Думаю, мне пришлось добавить "mode=pre-process" к первому <xsl:template... так что я <xsl:template mode = "pre-process" match = "/"> Это устранило ошибку, которую я получал, но у меня не было времени проверить, действительно ли выполняется предварительная обработка. еще в обработке, потому что мне нужно добавить свой код в конвейер.xsl - я опубликую немного позже, если смогу это подтвердить.

user555303 09.08.2024 16:27

поэтому добавление mode=pre-process к первому <xsl:template... избавило от ошибки, но после того, как я добавил свой код в конвейер.xsl, когда я тестирую, он запускает не мой код предварительной обработки, а скорее в основном использует XSLT третьей части, поэтому сейчас я собираюсь попробовать предложение Дэниела Хейли...

user555303 09.08.2024 16:57

Я попробовал, как предложил Дэниел Хейли, но, похоже, он по-прежнему выполняет только стороннее преобразование. Я могу сказать, что он использует сторонний XSLT, потому что этот XSLT приводит к тому, что выходные данные представляют собой текст, а не XML. Есть идеи, почему он даже не пытается выполнить преобразование, находящееся в самом файле Pipeline.xsl?

user555303 09.08.2024 17:25

К вашему сведению, я добавлю пример двух XSLT, которые мне нужно запустить последовательно, а также образец запроса/XML через несколько минут. Извините, потребовалось время, чтобы собрать это воедино.

user555303 09.08.2024 20:45

ок, обновил ОП новыми файлами!

user555303 09.08.2024 21:22

@ConalTuohy - я только что получил файлы, которые вы просили ранее, но, поскольку вы изменили подход и файлы, которые публикуете, я думаю, что для меня имеет смысл (а) попытаться запустить ваши новые файлы как есть, чтобы проверить, что я получите те же результаты, что и вы, затем (б) я изменю то, что вы предоставили, чтобы использовать настоящую/полную предварительную обработку и сторонние XLST, а затем (в) сообщу о том, что произойдет. Это звучит нормально? К вашему сведению, я не уверен, смогу ли я сделать все это сегодня вечером (сейчас 2:15 ночи)...

user555303 10.08.2024 08:14

@ConalTuohy - Когда я запускаю xsltproc с вашими файлами, я получаю описанный вами результат... поэтому я постараюсь приспособиться к вашему новому подходу... и дам вам знать

user555303 10.08.2024 08:30

@ConalTuohy - я поменял местами свои настоящие файлы XSLT, а также входной XML-файл, и когда я запускаю xsltproc -o output.txt Pipeline.xsl input.xml, он не создает файл output.txt. И ошибок тоже не выдает :(...

user555303 10.08.2024 08:47

@ConalTuohy - ИЗВИНИТЕ ЗА ПАНИКУ!!! Я понял, что мне нужно зайти в pre-processor.xsl и добавить mode = "pre-process" к командам шаблона, и я протестировал еще раз, и теперь это работает!!! Я ХОЧУ ПРОВЕСТИ БОЛЕЕ ПОДРОБНОЕ ТЕСТИРОВАНИЕ ЗАВТРА И НАПИШУ ОТВЕТ.... СПАСИБО!!

user555303 10.08.2024 08:57

КСТАТИ, это ТАК КРУТО :) !!

user555303 10.08.2024 09:04

Без проблем! Требование импортировать другую таблицу стилей, не прибегая к ее изменению, означало, что проблема требовала неочевидного трюка, найти решение которого было интересно. Обратите внимание, что в современной версии XSLT подобные вещи намного проще, но, к сожалению, до сих пор существует много-много программных платформ, которые поддерживают только эту уже древнюю версию языка (25 лет!). В XSLT 3 вы можете вызвать другой XSLT, используя функцию transform(), в результате чего длина pipeline.xsl составит всего несколько строк.

Conal Tuohy 10.08.2024 10:01

@ConalTuohy - Я согласен насчет ситуации с версией 1.0... это просто смешно. Я собираюсь попытаться протестировать XSLT на реальном продукте где-нибудь на этих выходных, и мы внутри компании обсуждаем возможность запроса на улучшение XSLT 3 от поставщика продукта, но даже если мы это сделаем, это все равно может не произойти во время наша жизнь (серьезно). Я опубликую после того, как опробую на реальном продукте.

user555303 10.08.2024 11:30

@ConalTuohy - я только что протестировал новый конвейер.xsl и т. д. с продуктом, и он сработал, поэтому после этого я отмечу ваш ответ. Спасибо, что остаетесь со мной в этом!!

user555303 10.08.2024 17:18

Другие вопросы по теме