У меня есть этот код нокогири, который работает медленнее, чем мне нравится на большом входе. Как бы вы повторили это в XSLT? Любые другие идеи, чтобы заставить его работать быстрее?
# remove namespaces (other then soapenv) from input xml, and move # them to type attribute. # xml is Nokogiri::XML object def cleanup_namespaces(xml) protected_ns = %w( soapenv ) xml.traverse do |el| next unless el.respond_to? :namespace if (ns=el.namespace) && !protected_ns.include?(ns.prefix) then el['type'] = "#{ns.prefix}:#{el.name}" el.namespace = nil end end xml end
Образец вход Я тестирую с:
<?xml version="1.0"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:getAccountDTOResponse xmlns:ns1="http://www.example.com/pw/services/PWServices" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <getAccountDTOReturn xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Account"> <ns1:ID soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:long">0</ns1:ID> <ns1:accountNumber xsi:type="soapenc:string" /> <ns1:accountType xsi:type="soapenc:string" /> <ns1:clientData xsi:type="soapenc:Array" xsi:nil="true" /> <ns1:name xsi:type="soapenc:string" /> <ns1:parentRef xsi:type="soapenc:string" /> </getAccountDTOReturn> </ns1:getAccountDTOResponse> </soapenv:Body> </soapenv:Envelope>
Ожидаемый выход :
<?xml version="1.0"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <getAccountDTOResponse xmlns:ns1="http://www.example.com/pw/services/PWServices" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" type="ns1:getAccountDTOResponse"> <getAccountDTOReturn xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Account"> <ID soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:long" type="ns1:ID">0</ID> <accountNumber xsi:type="soapenc:string" type="ns1:accountNumber" /> <accountType xsi:type="soapenc:string" type="ns1:accountType" /> <clientData xsi:type="soapenc:Array" xsi:nil="true" type="ns1:clientData" /> <name xsi:type="soapenc:string" type="ns1:name" /> <parentRef xsi:type="soapenc:string" type="ns1:parentRef" /> </getAccountDTOReturn> </getAccountDTOResponse> </soapenv:Body> </soapenv:Envelope>
Этот вход является ответом SOAP. Тангенциальный вопрос: что такое точка пространства имен типа ns1 в ответе SOAP, и является ли она разумно выбросить их полностью. Мне не нужно ссылаться на них при разборе ответа.
Этот XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="@* | node()" name="identity"> <xsl:copy> <xsl:apply-templates select="@* | node()" /> </xsl:copy> </xsl:template> <xsl:template match="*[namespace-uri() = 'http://www.example.com/pw/services/PWServices']"> <xsl:element name="{local-name()}"> <xsl:attribute name="type"> <xsl:value-of select="name()"/> </xsl:attribute> <xsl:apply-templates select="@* | node()"/> </xsl:element> </xsl:template> </xsl:stylesheet>
Против вашего образца даст такой результат:
<?xml version="1.0" encoding="UTF-16"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <getAccountDTOResponse type="ns1:getAccountDTOResponse" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <getAccountDTOReturn soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Account" xmlns:ns1="http://www.example.com/pw/services/PWServices" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices"> <ID type="ns1:ID" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:long">0</ID> <accountNumber type="ns1:accountNumber" xsi:type="soapenc:string"></accountNumber> <accountType type="ns1:accountType" xsi:type="soapenc:string"></accountType> <clientData type="ns1:clientData" xsi:type="soapenc:Array" xsi:nil="true"></clientData> <name type="ns1:name" xsi:type="soapenc:string"></name> <parentRef type="ns1:parentRef" xsi:type="soapenc:string"></parentRef> </getAccountDTOReturn> </getAccountDTOResponse> </soapenv:Body> </soapenv:Envelope>