Может ли кто-нибудь объяснить, как работает приведенный ниже xsl?

#xslt #xslt-3.0

Вопрос:

Может ли кто-нибудь объяснить, пожалуйста, как работает приведенный ниже xsl на примере?

 
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <!--  Remove empty elements or attributes -->
        <xsl:template match="@*|node()">
            <xsl:if test=". != '' or ./@* != ''">
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>

 

Когда я использую выше xsl для ниже xml, который не имеет отступа (обратите внимание, что он показывает отступ ниже, но считайте, что он не имеет отступа. Текстовое поле ввода не позволяло мне вставлять xml без отступов):

 
<Book Edition="1234" Type="Novel" TimeStamp="2021-07-09T14:02:55-05:00" Version="1.003">
    <BOS>
        <LIB>
            <RequestorID ID="XXX" Type="10"/>
        </LIB>
    </BOS>
    <Sections>
        <Section CreateDateTime="2021-07-03T11:21:43-05:00" CreatorID="XXX" Status="Read">
            <UniqueID ID="443791" Type="10"/>
            <Chapters>
                <Chapter>
                    <Paragraphs>
                        <Paragraph NumberOfUnits="10" Lines="100">
                            <Rates>
                                <Rate EffectiveDate="2021-12-12" ExpireDate="2021-12-13" RateTimeUnit="Day" UnitMultiplier="1">
                                    <Base AmountBeforeTax="145.90" CurrencyCode="USD"/>
                                </Rate>
                            </Rates>
                        </Paragraph>
                    </Paragraphs>
                    <Readers>
                        <Reader Age="10" Count="1"/>
                    </Readers>
                    <TimeSpan End="2021-12-13" Start="2021-12-12"/>
                    <BasicInfo BookCode="1310"/>
                </Chapter>
            </Chapters>
            <Authors>
                <Author AuthorRPH="1">
                    <Profiles>
                        <ProfileInfo>
                            <UniqueID ID="44379" Type="1"/>
                            <Profile ProfileType="1">
                                <Author>
                                    <PersonName>
                                        <GivenName>TEST</GivenName>
                                        <Surname>TEST</Surname>
                                    </PersonName>
                                    <Telephone PhoneNumber="0"/>
                                    <Email>test@test.com</Email>
                                    <Address Type="H">
                                        <AddressLine>123 MAIN ST</AddressLine>
                                    </Address>
                                </Author>
                            </Profile>
                        </ProfileInfo>
                    </Profiles>
                </Author>
            </Authors>
            <GlobalInfo>
                <ReadIds>
                    <ReadId ReadID_Source="ZZZ" ReadID_Type="10" ReadID_Value="1234"/>
                </ReadIds>
            </GlobalInfo>
        </Section>
    </Sections>
</Book>

 

Затем я получаю результат ниже:

 
         <Book Edition="1234" Type="Novel" TimeStamp="2021-07-09T14:02:55-05:00" Version="1.003">
                <BOS>
                    <LIB>
                        <RequestorID ID="XXX" Type="10"/>
                    </LIB>
                </BOS>
                <Sections>
                    <Section CreateDateTime="2021-07-03T11:21:43-05:00" CreatorID="XXX" Status="Read">
                        <UniqueID ID="443791" Type="10"/>
                        <Authors>
                            <Author AuthorRPH="1">
                                <Profiles>
                                    <ProfileInfo>
                                        <UniqueID ID="44379" Type="1"/>
                                        <Profile ProfileType="1">
                                            <Author>
                                                <PersonName>
                                                    <GivenName>TEST</GivenName>
                                                    <Surname>TEST</Surname>
                                                </PersonName>
                                                <Telephone PhoneNumber="0"/>
                                                <Email>test@test.com</Email>
                                                <Address Type="H">
                                                    <AddressLine>123 MAIN ST</AddressLine>
                                                </Address>
                                            </Author>
                                        </Profile>
                                    </ProfileInfo>
                                </Profiles>
                            </Author>
                        </Authors>
                    </Section>
                </Sections>
            </Book>
 

As seen above it removes everything inside the Chapters tag and Global info tag

But if i use above xsl for below xml which indented:

 
        <Book Edition="1234" Type="Novel" TimeStamp="2021-07-09T14:02:55-05:00" Version="1.003">
            <POS>
                <Source>
                    <RequestorID ID="XXX" Type="10"/>
                </Source>
            </POS>
            <Sections>
                <Section CreateDateTime="2021-07-03T11:21:43-05:00" CreatorID="XXX" Status="Read">
                    <UniqueID ID="443791" Type="10"/>
                    <Chapters>
                        <Chapter>
                            <Paragraphs>
                                <Paragraph NumberOfUnits="10" Lines="100">
                                    <Rates>
                                        <Rate EffectiveDate="2021-12-12" ExpireDate="2021-12-13" RateTimeUnit="Day" UnitMultiplier="1">
                                            <Base AmountBeforeTax="145.90" CurrencyCode="USD"/>
                                        </Rate>
                                    </Rates>
                                </Paragraph>
                            </Paragraphs>
                            <Readers>
                                <Reader Age="10" Count="1"/>
                            </Readers>
                            <TimeSpan End="2021-12-13" Start="2021-12-12"/>
                        
                            <BasicInfo BookCode="1310"/>
                        </Chapter>
                    </Chapters>
                    <Authors>
                        <Author AuthorRPH="1">
                            <Profiles>
                                <ProfileInfo>
                                    <UniqueID ID="44379" Type="1"/>
                                    <Profile ProfileType="1">
                                        <Author>
                                            <PersonName>
                                                <GivenName>TEST</GivenName>
                                                <Surname>TEST</Surname>
                                            </PersonName>
                                            <Telephone PhoneNumber="0"/>
                                            <Email>test@test.com</Email>
                                            <Address Type="H">
                                                <AddressLine>123 MAIN ST</AddressLine>
                                            </Address>
                                        </Author>
                                    </Profile>
                                </ProfileInfo>
                            </Profiles>
                        </Author>
                    </Authors>
                    <GlobalInfo>
                        <ReadIds>
                            <ReadId ReadID_Source="ZZZ" ReadID_Type="10" ReadID_Value="1234"/>
                        </ReadIds>
                    </GlobalInfo>
                </Section>
            </Sections>
        </Book>

 

Затем я получаю правильный вывод:

  

       <Book Edition="1234" Type="Novel" TimeStamp="2021-07-09T14:02:55-05:00" Version="1.003">
            <BOS>
                <LIB>
                    <RequestorID ID="XXX" Type="10"/>
                </LIB>
            </BOS>
            <Sections>
                <Section CreateDateTime="2021-07-03T11:21:43-05:00" CreatorID="XXX" Status="Read">
                    <UniqueID ID="443791" Type="10"/>
                    <Chapters>
                        <Chapter>
                            <Paragraphs>
                                <Paragraph NumberOfUnits="10" Lines="100">
                                    <Rates>
                                        <Rate EffectiveDate="2021-12-12" ExpireDate="2021-12-13" RateTimeUnit="Day" UnitMultiplier="1">
                                            <Base AmountBeforeTax="145.90" CurrencyCode="USD"/>
                                        </Rate>
                                    </Rates>
                                </Paragraph>
                            </Paragraphs>
                            <Readers>
                                <Reader Age="10" Count="1"/>
                            </Readers>
                            <TimeSpan End="2021-12-13" Start="2021-12-12"/>
                            <BasicInfo BookCode="1310"/>
                        </Chapter>
                    </Chapters>
                    <Authors>
                        <Author AuthorRPH="1">
                            <Profiles>
                                <ProfileInfo>
                                    <UniqueID ID="44379" Type="1"/>
                                    <Profile ProfileType="1">
                                        <Author>
                                            <PersonName>
                                                <GivenName>TEST</GivenName>
                                                <Surname>TEST</Surname>
                                            </PersonName>
                                            <Telephone PhoneNumber="0"/>
                                            <Email>test@test.com</Email>
                                            <Address Type="H">
                                                <AddressLine>123 MAIN ST</AddressLine>
                                            </Address>
                                        </Author>
                                    </Profile>
                                </ProfileInfo>
                            </Profiles>
                        </Author>
                    </Authors>
                    <GlobalInfo>
                        <ReadIds>
                            <ReadId ReadID_Source="ZZZ" ReadID_Type="10" 
    ReadID_Value="1234"/>
                        </ReadIds>
                    </GlobalInfo>
                </Section>
            </Sections>
        </Book>

 

Может ли кто-нибудь объяснить, если xml одинаковы, почему отступы дают разные выходные данные? Влияет ли правильный отступ на преобразование xsl?

Комментарии:

1. Он выполняет преобразование идентификатора с добавленным фильтром для пустых элементов.

Ответ №1:

Код имеет одно правило шаблона, которое соответствует всем элементам, тексту, комментарию, инструкции по обработке и узлам атрибутов. Если узел имеет непустое строковое значение или имеет атрибут с непустым строковым значением, он копирует узел и рекурсивно обрабатывает его атрибуты и дочерние элементы.

Общий эффект заключается в копировании всего документа, за исключением элементов, которые не имеют содержимого и непустых атрибутов (таких как <br/> ), плюс несколько других исключений, таких как пустые комментарии.

Ответ №2:

Выражение XPath . != '' or ./@* != '' в тесте может вести себя не так, как вы ожидаете. Спецификация для XPath 1.0 (обычно используется с XSLT 1.0), как version="1.0" указано в https://www.w3.org/TR/1999/REC-xpath-19991116/#dt-string-value

Для каждого типа узла существует способ определения строкового значения для узла этого типа. Для некоторых типов узлов строковое значение является частью узла; для других типов узлов строковое значение вычисляется из строкового значения узлов-потомков.

и далее в разделе «Узлы элементов 5.2»

Строковое значение узла элемента представляет собой объединение строковых значений всех потомков текстового узла узла элемента в порядке документа.

Таким образом, для обычного исходного элемента без отступа преобразование строк включает рекурсивное нисхождение к элементам и получение их значений (игнорирование атрибутов). В вашем случае для элемента, у которого также нет атрибутов, все поддерево удаляется (т. Е. Не копируется для вывода), если в нем нет элемента со значением, подобным <elem>value</elem> этому.

С источником с отступом у вас также есть узлы, представляющие пробелы между узлами. (XPath не знает, что пробелы для вас не имеют значения, и предполагает смешанное содержимое.) Это приводит к преобразованию в строку элемента с (отступами) подэлементами, которые (по крайней мере) содержат пробелы в результате преобразования строки, . != '' что делает выражение XPath ложным.

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

Возможно, вы захотите взглянуть на https://www.w3.org/TR/1999/REC-xpath-19991116/#function-normalize-space для обрезки результата преобразования. Обратите внимание, что это потенциально также повлияет на соблюдение «реальных ценностей», если все они могут быть пробелами.

Изменить: В зависимости от того, чего вы хотите достичь, вы можете рассмотреть возможность устранения пробелов процессором XSLT с помощью xsl:пробел.

Комментарии:

1. Считается ли пробел между двумя тегами текстовым узлом? Или если теги находятся в новой строке каждый, как показано ниже, то эта новая строка рассматривается как текстовый узел? <Главы> <Главы><Глава> или <Глава><Главы> <Главы><Главы > < Глава>

2. Да, пробелы между двумя тегами сопоставляются текстовому узлу. Он содержит все символы, т. е. не только строку ввода, но также вкладки и пробелы. Если вы используете xsl:пробел , эти текстовые узлы будут удалены до обработки.