Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > XML, XSL > Помогите разобраться с циклом


Автор: EgoBrain 17.10.2016, 10:19
Почему результат цикла, это значение первого подъэлемента каждого набора? Как сделать правильно?
Исходные данные:
Код

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <S:Body wsu:Id="body">
        <ns8:getPersonalCertificateBirthResponse xmlns:ns8="http://zags.minjust.ru/fzags/interdeppersonalservice/type/" xmlns="http://zags.minjust.ru/fzags/interdeppersonalservice/type/document/" xmlns:ns2="http://zags.minjust.ru/fzags/interdeppersonalservice/type/common/" xmlns:ns3="http://zags.minjust.ru/fzags/interdeppersonalservice/type/actor/" xmlns:ns4="http://zags.minjust.ru/fzags/interdeppersonalservice/type/local/" xmlns:ns5="http://smev.gosuslugi.ru/rev120315" xmlns:ns6="http://www.w3.org/2000/09/xmldsig#" xmlns:ns7="http://www.w3.org/2004/08/xop/include">
            <ns5:MessageData>
                <ns5:AppData Id="AppData">
                    <ns4:certificateBirthResponseObj>
                        <ns4:certificateBirth>
                            <actRecordNumber>9999</actRecordNumber>
                        </ns4:certificateBirth>
                        <certRequisites>
                            <ns2:item>
                                <ns2:certIssueDate>2014-08-12T00:00:00+11:00</ns2:certIssueDate>
                                <ns2:certNumber>111112</ns2:certNumber>
                                <ns2:certSeries>I - ХР</ns2:certSeries>
                            </ns2:item>
                            <ns2:item>
                                <ns2:certIssueDate>2015-10-12T00:00:00+11:00</ns2:certIssueDate>
                                <ns2:certNumber>2222</ns2:certNumber>
                                <ns2:certSeries>S</ns2:certSeries>
                            </ns2:item>
                            <ns2:item>
                                <ns2:certIssueDate>2016-01-12T00:00:00+11:00</ns2:certIssueDate>
                                <ns2:certNumber>3333333</ns2:certNumber>
                                <ns2:certSeries>M</ns2:certSeries>
                            </ns2:item>
                        </certRequisites>
                    </ns4:certificateBirthResponseObj>                    
                </ns5:AppData>
            </ns5:MessageData>
        </ns8:getPersonalCertificateBirthResponse>
    </S:Body>
</S:Envelope>


Шаблон преобразования:
Код

<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">

        <soapenv:Envelope 
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
        xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
        xmlns:type="http://zags.minjust.ru/fzags/interdeppersonalservice/type/" 
        xmlns:rev="http://smev.gosuslugi.ru/rev120315" 
        xmlns:inc="http://www.w3.org/2004/08/xop/include" 
        xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <soapenv:Header/>
            <soapenv:Body>
                <params>
                        <CertRequisites>
                            <xsl:for-each select="//*[local-name()='certificateBirthResponseObj']/*[local-name()='certRequisites']/*">
                                <CertRequisites>
                                    <certIssueDate>
                                        <xsl:value-of select="*certIssueDate" />
                                    </certIssueDate>                                    
                                    <certNumber>
                                        <xsl:value-of select="*certNumber" />
                                    </certNumber>
                                    <certSeries>
                                        <xsl:value-of select="*certSeries" />
                                    </certSeries>
                                </CertRequisites>
                            </xsl:for-each> 
                        </CertRequisites>                    
                </params>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>
</xsl:stylesheet>


Что получаю:
Код

...
         <CertRequisites>
            <CertRequisites>
               <certIssueDate>2014-08-12T00:00:00+11:00</certIssueDate> <!-- В каждый дочерний элемент набора получаю значение из первого элемента набора -->
               <certNumber>2014-08-12T00:00:00+11:00</certNumber>
               <certSeries>2014-08-12T00:00:00+11:00</certSeries>
            </CertRequisites>
            <CertRequisites>
               <certIssueDate>2015-10-12T00:00:00+11:00</certIssueDate>
               <certNumber>2015-10-12T00:00:00+11:00</certNumber>
               <certSeries>2015-10-12T00:00:00+11:00</certSeries>
            </CertRequisites>
            <CertRequisites>
               <certIssueDate>2016-01-12T00:00:00+11:00</certIssueDate>
               <certNumber>2016-01-12T00:00:00+11:00</certNumber>
               <certSeries>2016-01-12T00:00:00+11:00</certSeries>
            </CertRequisites>
         </CertRequisites>
      ...

Автор: diadiavova 17.10.2016, 12:00
Цитата(EgoBrain @  17.10.2016,  10:19 Найти цитируемый пост)
Почему результат цикла, это значение первого подъэлемента каждого набора?

Поясни, что конкретно тебя не устраивает и как, по-твоему, должен выглядеть результат. В твоем случае результатом выражения //*[local-name()='certificateBirthResponseObj']/*[local-name()='certRequisites']/* будут элементы ns2:item, коих в документе ровно три штуки. В результирующем документе, каждому из этих айтемов соответствует блок, который ты формируешь в фор-ич. Данные для каждого блока так же берутся из соответствующих айтемов. Что не так?

Автор: EgoBrain 18.10.2016, 01:37
Цитата(diadiavova @ 17.10.2016,  12:00)
Что не так?

Ну очевидно же что не так, за что ты меня так наказываешь ожиданием в еще один зря потраченный рабочий день  smile 
В результирующем наборе я получаю
Цитата

<CertRequisites>
               <certIssueDate>2015-10-12T00:00:00+11:00</certIssueDate>
               <certNumber>2015-10-12T00:00:00+11:00</certNumber>
               <certSeries>2015-10-12T00:00:00+11:00</certSeries>
</CertRequisites>

А нужно так:
Цитата

<CertRequisites>
               <certIssueDate>2015-10-12T00:00:00+11:00</certIssueDate>
               <certNumber>2222</certNumber>
               <certSeries>S</certSeries>
</CertRequisites>

Цитата

Почему результат цикла, это значение первого подъэлемента каждого набора? Как сделать правильно?


Добавлено @ 01:41
Цитата(diadiavova @ 17.10.2016,  12:00)
В твоем случае результатом выражения //*[local-name()='certificateBirthResponseObj']/*[local-name()='certRequisites']/* будут элементы ns2:item, коих в документе ровно три штуки. В результирующем документе, каждому из этих айтемов соответствует блок, который ты формируешь в фор-ич.

То есть мне нужен вложенный цикл? Первый будет по item, второй по его элементам.
Цитата(diadiavova)
Данные для каждого блока так же берутся из соответствующих айтемов.

Не из соответствующих а только из первого. В каждом айтеме кроме даты есть еще и число и строка, а получаю я только дату.

Автор: EgoBrain 18.10.2016, 09:26
Разобрался. Всё оказалось как ты и сказал 
Цитата
программа, обрабатывающая XPath должна быть извещена о значении префиксов, чтобы можно было сопоставить их пространствам имен. Судя по тому, что в соседней теме ты что-то подобное использовал в XSLT, по всей видимости именно в нем тебе это и нужно. Ну тут все просто: поскольку XSLT сам является словарем XML, стало быть правила тут те же, что и в любом XML - объяви нужные тебе пространства имен в корневом элементе преобразования и все заработает как надо.

Добавил в шаблон объявления пространств имен и подправил немного обращение к самим элементам.
Код

<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <soapenv:Envelope 
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
        xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
        xmlns:type="http://zags.minjust.ru/fzags/interdeppersonalservice/type/" 
        xmlns:rev="http://smev.gosuslugi.ru/rev120315" 
        xmlns:inc="http://www.w3.org/2004/08/xop/include" 
        xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
 xmlns:ns8="http://zags.minjust.ru/fzags/interdeppersonalservice/type/" xmlns="http://zags.minjust.ru/fzags/interdeppersonalservice/type/document/" xmlns:ns2="http://zags.minjust.ru/fzags/interdeppersonalservice/type/common/" xmlns:ns3="http://zags.minjust.ru/fzags/interdeppersonalservice/type/actor/" xmlns:ns4="http://zags.minjust.ru/fzags/interdeppersonalservice/type/local/" xmlns:ns5="http://smev.gosuslugi.ru/rev120315" xmlns:ns6="http://www.w3.org/2000/09/xmldsig#" xmlns:ns7="http://www.w3.org/2004/08/xop/include"> <!-- Объявления пространств -->
            <soapenv:Header/>
            <soapenv:Body>
                <params>
                        <CertRequisites>
                            <xsl:for-each select="//*[local-name()='certificateBirthResponseObj']/*[local-name()='certRequisites']/*">
                                <CertRequisites>
                                    <certIssueDate>
                                        <xsl:value-of select="ns2:certIssueDate" /> <!-- Префикс пространства у элемента -->
                                    </certIssueDate>                                    
                                    <certNumber>
                                        <xsl:value-of select="ns2:certNumber" />
                                    </certNumber>
                                    <certSeries>
                                        <xsl:value-of select="ns2:certSeries" />
                                    </certSeries>
                                </CertRequisites>
                            </xsl:for-each> 
                        </CertRequisites>                    
                </params>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>
</xsl:stylesheet>

Автор: diadiavova 18.10.2016, 10:10
Цитата(EgoBrain @  18.10.2016,  01:37 Найти цитируемый пост)
Не из соответствующих а только из первого. В каждом айтеме кроме даты есть еще и число и строка, а получаю я только дату.

Да, я здесь невнимательно посмотрел, просто в каждом айтеме дата вроде своя была, а поскольку ты там что-то о цикле говорил(хоть фор-ич и не цикл, ну да ладно), я там дальше уже не стал смотреть. 
У тебя там была применена такая конструкция *elementname. Насколько я понимаю, это вообще синтаксическая ошибка, но судя по результату процессор принял этот странный конструкт просто за звездочку, проигнорировав остальное. Ну, а дальше все просто: валью-оф возвращает значение одного узла, а если ему передать набор, то используется только первый узел.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)