Имя: Пароль:
1C
1C 7.7
v7: Как выбрать узел XML по неполному имени (без пространства имен)?
,
0 antgenp
 
25.08.16
14:45
Добрый день!
Есть задача - считывание xml-файлика. Она была реализована через анализатор XML v7plus.dll. Но, как оказалось, сервер пропускает и обрабатывает ответы с различными пространствами имен в файлах XML. Т.е. пространство имён может быть пустым, может быть "ns:", может быть "ns6", - и это только то, что реально попадается. Соответственно, реализация, где узел выбирался по каноническому имени (КорневойЭлемент.ВыбратьУзел("ns:НужныйУзел")) сработает только при полном совпадении и имени узла, и пространства имен. Условие метода "ВыбратьУзел" пишется, как я понял, на XSLT(?), должно быть составлено в соответствии со стандартами XPATH. Поискал в интернете варианты, как это можно сделать - под саму 1с 7.7 не нашел реализаций, но нашел, например, в описании XPATH функцию local-name(), которая возвращает имя узла без наименования пространства имен, т.е., казалось бы, как раз то, что нужно. Но, увы, никак не пойму, можно ли в условии выбора для метода 1с 7.7 "ВыбратьУзел" использовать предикат (условие). У меня, по крайней мере, не получилось. Пробовал, например, следующий вариант:
ВыбратьУзел("./*[local-name()='НужныйУзел']")  
1С выдает ошибку: Ошибка исполнения метода.
У меня вообще не получилось ни одну функцию XPATH засунуть в условие метода - всегда получал ошибку. Может быть, я что-то делаю не так, как нужно? Или есть какая-то другая возможность сделать потребное?
Или нужно идти через объявление пространства имен?
У меня пока остался единственный вариант - прописать все варианты через оператор логического или "|" :
ВыбратьУзел("ns:НужныйУзел|ns6:НужныйУзел|НужныйУзел")
Но со временем могут добавиться новые пространства имен, а каждый раз отслеживать и своевременно их добавлять проблемно.
Можете помочь решить как-то проблему?
1 antgenp
 
25.08.16
14:57
Делается это для ЕГАИС, проблемы обнаружилась в актах от клиентов.
Примеры файликов:
<ns:Documents xmlns:ns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01">;
<ns:Owner>
<ns:FSRAR_ID>020000231871</ns:FSRAR_ID>
</ns:Owner>
<ns:Document>
<WayBillAct xmlns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01">;
<Identity xmlns="http://fsrar.ru/WEGAIS/ActTTNSingle">1</Identity>;
<Header xmlns="http://fsrar.ru/WEGAIS/ActTTNSingle">;
<IsAccept>Accepted</IsAccept>
<ACTNUMBER>714d5482-ecc8-4885-8e6b-64e2472664cf</ACTNUMBER>
<ActDate>2016-02-08</ActDate>
<WBRegId>TTN-0005560863</WBRegId>
</Header>
<Content xmlns="http://fsrar.ru/WEGAIS/ActTTNSingle"/>;
</WayBillAct>
</ns:Document>
</ns:Documents>


<ns:Documents xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xmlns:ns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01"; xmlns:oref="http://fsrar.ru/WEGAIS/ClientRef"; xmlns:pref="http://fsrar.ru/WEGAIS/ProductRef"; xmlns:wa="http://fsrar.ru/WEGAIS/ActTTNSingle"; Version="1.0">
<ns:Owner>
<ns:FSRAR_ID>030000159487</ns:FSRAR_ID>
</ns:Owner>
<ns:Document>
<ns:WayBillAct>
<wa:Header>
<wa:IsAccept>Accepted</wa:IsAccept>
<wa:ACTNUMBER>МИ00000801</wa:ACTNUMBER>
<wa:ActDate>2016-01-26</wa:ActDate>
<wa:WBRegId>TTN-0003442235</wa:WBRegId>
<wa:Note>Note</wa:Note>
</wa:Header>
<wa:Content></wa:Content>
</ns:WayBillAct>
</ns:Document>
</ns:Documents>


<Documents xmlns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01"; xmlns:ns2="http://fsrar.ru/WEGAIS/TTNSingle"; xmlns:ns3="http://fsrar.ru/WEGAIS/ClientRef"; xmlns:ns4="http://fsrar.ru/WEGAIS/ProductRef"; xmlns:ns5="http://fsrar.ru/WEGAIS/Ticket"; xmlns:ns6="http://fsrar.ru/WEGAIS/ActTTNSingle"; xmlns:ns7="http://fsrar.ru/WEGAIS/ConfirmTicket"; xmlns:ns8="http://fsrar.ru/WEGAIS/TTNInformBReg"; xmlns:ns9="http://fsrar.ru/WEGAIS/ActInventorySingle"; xmlns:ns10="http://fsrar.ru/WEGAIS/ActInventoryABInfo"; xmlns:ns11="http://fsrar.ru/WEGAIS/ActChargeOn"; xmlns:ns12="http://fsrar.ru/WEGAIS/ActInventoryInformBReg"; xmlns:ns13="http://fsrar.ru/WEGAIS/QueryParameters"; xmlns:ns14="http://fsrar.ru/WEGAIS/QueryFormAB"; xmlns:ns15="http://fsrar.ru/WEGAIS/ReplySSP"; xmlns:ns16="http://fsrar.ru/WEGAIS/ReplySpirit"; xmlns:ns17="http://fsrar.ru/WEGAIS/ReplyClient"; xmlns:ns18="http://fsrar.ru/WEGAIS/ReplyAP"; xmlns:ns19="http://fsrar.ru/WEGAIS/ReplyRests"; xmlns:ns20="http://fsrar.ru/WEGAIS/ReplyFormA"; xmlns:ns21="http://fsrar.ru/WEGAIS/ReplyFormB"; xmlns:ns22="http://fsrar.ru/WEGAIS/ActWriteOff">;
<Owner>
<FSRAR_ID>030000033639</FSRAR_ID>
</Owner>
<Document>
<WayBillAct>
<ns6:Header>
<ns6:IsAccept>Accepted</ns6:IsAccept>
<ns6:ACTNUMBER>A-МИ00001743</ns6:ACTNUMBER>
<ns6:ActDate>2016-02-10</ns6:ActDate>
<ns6:WBRegId>TTN-0006564090</ns6:WBRegId>
<ns6:Note/>
</ns6:Header>
<ns6:Content/>
</WayBillAct>
</Document>
</Documents>
2 antgenp
 
25.08.16
16:39
АП
Приношу свои извинения за форматирование примеров - если подскажите, как пост можно отредактировать, исправлюсь.
Ещё раз вкратце проблема:
Приходят XML с одними и теми же собственными именами узлов, но разными пространствами имен. В остальном всё то же самое.
Пример:
<Header></Header>
<ns:Header></ns:Header>
<ns6:Header><ns6:Header>

Могу я с помощью метода ВыбратьУзел() v7plus.dll в 1с 7.7 выбрать узел с наименованием Header без оглядки на пространство имен?
Или в какую сторону идти курить мануалы?
3 Djelf
 
25.08.16
16:50
(0) Можно убрать все пространства имен и работать без них.

Функция   хмлУдалитьПространствоИмен(хмлСообщение) //:MSXML2.DOMDocument
    xslDoc=СоздатьОбъект("MSXML2.DOMDocument");
    xslDoc.async = 0;
    xslDoc.loadXML("
    |<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">;
    |    <xsl:output method=""xml"" version=""1.0"" encoding=""UTF-8"" omit-xml-declaration=""yes"" indent=""yes""/>
    |    <xsl:strip-space elements=""*""/>
    |
    |    <!-- keep comments -->
    |    <xsl:template match=""comment()"">
    |        <xsl:copy>
    |        <xsl:apply-templates/>
    |    </xsl:copy>
    |    </xsl:template>
    |    <xsl:template match=""*"">
    |        <!-- remove element prefix -->
    |        <xsl:element name=""{local-name(.)}"">
    |            <!-- process attributes -->
    |            <xsl:for-each select=""@*"">
    |                <!-- remove attribute prefix -->
    |                <xsl:attribute name=""{local-name(.)}"">
    |                    <xsl:value-of select=""normalize-space(.)""/>
    |                </xsl:attribute>
    |            </xsl:for-each>
    |            <xsl:apply-templates/>
    |        </xsl:element>
    |    </xsl:template>
    |</xsl:stylesheet>
    |");
    xmlDoc=СоздатьОбъект("MSXML2.DOMDocument");
    хмлСообщение.transformNodeToObject(xslDoc, xmlDoc);
    Возврат xmlDoc;
КонецФункции
4 antgenp
 
25.08.16
16:58
Спасибо, сегодня попробую.
5 antgenp
 
26.08.16
09:07
Не выходит.
Выдает ошибку:
msxml3.dll: Ключевое слово "xsl:stylesheet" не может содержать узлы "PCDATA".
6 antgenp
 
26.08.16
11:47
Погуглил, нашел немного другой вариант:


Функция   хмлУдалитьПространстваИмен(хмлСообщение) //:MSXML2.DOMDocument

    xslDoc=СоздатьОбъект("MSXML2.DOMDocument");

    xslDoc.async = 0;

    xslDoc.loadXML("
        |<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">;
    |<xsl:output method=""xml""/>
    |<xsl:template match=""/"">
    |<xsl:copy>
    |<xsl:apply-templates />
    |</xsl:copy>
    |</xsl:template>
    |<xsl:template match=""*"">
    |<xsl:element name=""{local-name()}"">
    |<xsl:apply-templates select=""@* | node()"" />
    |</xsl:element>
    |</xsl:template>
    |<xsl:template match=""@*"">
    |<xsl:attribute name=""{local-name()}""><xsl:value-of select="".""
    |/></xsl:attribute>
    |</xsl:template>
    |<xsl:template match=""text() | processing-instruction() | comment()"">
    |<xsl:copy />
    |</xsl:template>
    |</xsl:stylesheet>
    |");

    xmlDoc=СоздатьОбъект("MSXML2.DOMDocument");

    хмлСообщение.transformNodeToObject(xslDoc, xmlDoc);

    Возврат xmlDoc;
КонецФункции


Сейчас тестирую, пока похоже, что работает так, как мне надо. Но, т.к. XSLT не знаю, то пока не уверен в этом )
Спасибо за помощь.
7 Djelf
 
26.08.16
12:42
(5) Ну я тоже не сам это преобразование придумал.
Странно... это выдернуто из рабочего модуля егаис, хотя для такой ошибки достаточно того чтобы одна буковка не так скопировалась.
8 antgenp
 
26.08.16
15:14
А рабочий модуль для семерки или для восьмерки?
У меня ещё были проблемы с любыми упоминаниями кодировки.
Ошибка была что-то вроде "Недопустимая кодировка" или как-то так,при чем пробовал менять указанную кодировку, ставил вариант с кодировкой из вашего примера, но ошибка всё равно сохранялась. Пришлось убрать все упоминания о кодировке.
А может быть это из-за различных версий платформы 1с?
9 Djelf
 
26.08.16
15:24
(8) Ну раз в коде СоздатьОбъект то 7ка.
Ты случаем в функцию не текст передашь? Туда MSXML2.DOMDocument передавать надо.
10 antgenp
 
26.08.16
16:09
Нет, не текст, но и не MSXML2.DOMDocument, а объект, загруженный с помощью анализатора XML v7plus.dll.
У меня всё было под него написано, поэтому, возможно, и не сработал твой пример.
С другой стороны, тот вариант, который я тебе написал, вроде работает и таким образом.
Получается, что у меня сейчас создается объект анализатора XML, потом я его передаю в функцию, функция возвращает элемент MSXML2.DOMDocument, продолжать работу с ним анализатор не может, поэтому его приходится снова открывать анализатором, благо в параметр анализатора можно как писать имя файла на диске, так и объект. Выглядит это так:

ПарсерХМЛ = СоздатьОбъект("AddIn.XMLParser");
ХМЛ = ПарсерХМЛ.СоздатьДокумент();
ХМЛ.Загрузить(ФайлОтвета);
xmlWithoutNamespaces= хмлУдалитьПространстваИмен(ХМЛ);
...
ХМЛ.Загрузить(xmlWithoutNamespaces);

Если можно сделать лучше или это дикая ересь, то подскажи как исправить, пожалуйста. Просто изначально всё было написано под анализатор, а таким образом получилось сделать с минимумом изменений.
11 antgenp
 
26.08.16
16:21
Если я правильно понимаю, анализатор XML v7plus.dll тоже работает через MSXML, но может не совпадать версия - сейчас глянул какие версии используются - ВерсияАнализатора 2.0, ВерсияБазовогоАнализатора 3.0.
Из этого мне не совсем понятно, MSXML2 или MSXML3 используется компонентой v7plus.dll, может быть проблема была в том, что всё-таки используется версия 3.0 а я её передавал в функцию для обработки 2-й версией. Соответственно, возникали ошибки из-за какого-то различия в понимании синтаксиса.
12 trad
 
29.08.16
09:51
(0) не нужно делать никакой обработки xml, ни выпиливание ns, ни xslt-преобразований, ни поиска по подстроке.

Нужно просто обучить свой DOMDocument. Сказать ему под каким псевдонимом ты ожидаешь увидеть каждый URI

В твоем случае делается это так:
ХМЛ=СоздатьОбъект("Msxml2.DOMDocument");
ХМЛ.setProperty("SelectionNamespaces", "xmlns:wa='http://fsrar.ru/WEGAIS/ActTTNSingle'&quot;);

И далее везде в коде работаешь через упомянутый wa
Номер = ДокXML.selectSingleNode("//wa:ACTNUMBER").text;
13 trad
 
29.08.16
09:53
А в целом, для работы с УТМ ЕГАИС у меня есть такая функция, где перечислены все используемые в УТМ URI и их типовые псевдонимы:

Функция СоздатьДокументОбменаУТМ()
    ПространстваИменУТМ = "
    |xmlns:ns='http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01'
    |xmlns:c='http://fsrar.ru/WEGAIS/Common'
    |xmlns:ce='http://fsrar.ru/WEGAIS/CommonEnum'
    |xmlns:oref='http://fsrar.ru/WEGAIS/ClientRef'
    |xmlns:pref='http://fsrar.ru/WEGAIS/ProductRef'
    |xmlns:wb='http://fsrar.ru/WEGAIS/TTNSingle'
    |xmlns:tc='http://fsrar.ru/WEGAIS/Ticket'
    |xmlns:wa='http://fsrar.ru/WEGAIS/ActTTNSingle'
    |xmlns:ctc='http://fsrar.ru/WEGAIS/ConfirmTicket'
    |xmlns:ain='http://fsrar.ru/WEGAIS/ActInventorySingle'
    |xmlns:ainp='http://fsrar.ru/WEGAIS/ActChargeOn'
    |xmlns:qp='http://fsrar.ru/WEGAIS/QueryParameters'
    |xmlns:wbr='http://fsrar.ru/WEGAIS/TTNInformBReg'
    |xmlns:aint='http://fsrar.ru/WEGAIS/ActInventoryInformBReg'
    |xmlns:qf='http://fsrar.ru/WEGAIS/QueryFormAB'
    |xmlns:awr='http://fsrar.ru/WEGAIS/ActWriteOff'
    |xmlns:rpp='http://fsrar.ru/WEGAIS/RepProducedProduct'
    |xmlns:rpi='http://fsrar.ru/WEGAIS/RepImportedProduct'
    |
    |xmlns:rssp='http://fsrar.ru/WEGAIS/ReplySSP'
    |xmlns:rs='http://fsrar.ru/WEGAIS/ReplySpirit'
    |xmlns:rc='http://fsrar.ru/WEGAIS/ReplyClient'
    |xmlns:rap='http://fsrar.ru/WEGAIS/ReplyAP'
    |xmlns:rst='http://fsrar.ru/WEGAIS/ReplyRests'
    |xmlns:rfa='http://fsrar.ru/WEGAIS/ReplyFormA'
    |xmlns:rfb='http://fsrar.ru/WEGAIS/ReplyFormB'
    |
    |xmlns:rfhb='http://fsrar.ru/WEGAIS/ReplyHistFormB'
    |xmlns:orefv='http://fsrar.ru/WEGAIS/ReplyClientVersion'
    |
    |xmlns:oref2='http://fsrar.ru/WEGAIS/ClientRef_v2'
    |xmlns:pref2='http://fsrar.ru/WEGAIS/ProductRef_v2'
    |xmlns:qrrp='http://fsrar.ru/WEGAIS/QueryRejectRepProduced'
    |xmlns:qrri='http://fsrar.ru/WEGAIS/QueryRejectRepImported'
    |
    |xmlns:rssp2='http://fsrar.ru/WEGAIS/ReplySSP_v2'
    |xmlns:rs2='http://fsrar.ru/WEGAIS/ReplySpirit_v2'
    |xmlns:rc2='http://fsrar.ru/WEGAIS/ReplyClient_v2'
    |xmlns:rap2='http://fsrar.ru/WEGAIS/ReplyAP_v2'
    |xmlns:rst2='http://fsrar.ru/WEGAIS/ReplyRests_v2'
    |xmlns:rfa2='http://fsrar.ru/WEGAIS/ReplyForm1'
    |xmlns:rfb2='http://fsrar.ru/WEGAIS/ReplyForm2'
    |xmlns:rfhb2='http://fsrar.ru/WEGAIS/ReplyHistForm2'
    |xmlns:wb2='http://fsrar.ru/WEGAIS/TTNSingle_v2'
    |xmlns:wa2='http://fsrar.ru/WEGAIS/ActTTNSingle_v2'
    |xmlns:ainp2='http://fsrar.ru/WEGAIS/ActChargeOn_v2'
    |xmlns:wbr2='http://fsrar.ru/WEGAIS/TTNInformF2Reg'
    |xmlns:aint2='http://fsrar.ru/WEGAIS/ActInventoryInformF2Reg'
    |xmlns:qf2='http://fsrar.ru/WEGAIS/QueryFormF1F2'
    |xmlns:awr2='http://fsrar.ru/WEGAIS/ActWriteOff_v2'
    |xmlns:tfs='http://fsrar.ru/WEGAIS/TransferFromShop'
    |xmlns:tts='http://fsrar.ru/WEGAIS/TransferToShop'
    |xmlns:ripf1='http://fsrar.ru/WEGAIS/RepInformF1Reg'
    |xmlns:nattn='http://fsrar.ru/WEGAIS/ReplyNoAnswerTTN'
    |xmlns:rsts2='http://fsrar.ru/WEGAIS/ReplyRestsShop_v2'
    |xmlns:asiu='http://fsrar.ru/WEGAIS/Asiiu'
    |xmlns:asiut='http://fsrar.ru/WEGAIS/AsiiuTime'
    |
    |xmlns:ains2='http://fsrar.ru/WEGAIS/ActChargeOnShop_v2'
    |xmlns:awrs2='http://fsrar.ru/WEGAIS/ActWriteOffShop_v2'
    |xmlns:wbfu='http://fsrar.ru/WEGAIS/InfoVersionTTN'
    |xmlns:qbc='http://fsrar.ru/WEGAIS/QueryBarcode'
    |xmlns:rbc='http://fsrar.ru/WEGAIS/ReplyBarcode'
    |xmlns:rrwb='http://fsrar.ru/WEGAIS/RequestRepealWB'
    |xmlns:crwb='http://fsrar.ru/WEGAIS/ConfirmRepealWB'
    |xmlns:rraco='http://fsrar.ru/WEGAIS/RequestRepealACO'
    |xmlns:rrawo='http://fsrar.ru/WEGAIS/RequestRepealAWO'    
    |";
    
    ДокXML = СоздатьОбъект("Msxml2.DOMDocument");
    ДокXML.setProperty("SelectionNamespaces", ПространстваИменУТМ);
    Возврат ДокXML;
КонецФункции
14 trad
 
29.08.16
09:55
получить актуальный список пространств имен можно в УТМ, в документе WB_DOC_SINGLE_01.xsd
15 sapphire
 
29.08.16
13:41
(0) Используйте Microsoft DOM Document.
Здесь можно обсудить любую тему при этом оставаясь на форуме для 1Сников, который нужен для работы. Ymryn