Я проверил много ответов здесь, и я думаю, что я почти там. Одна вещь, которая прослушивает меня (и по некоторым причинам для моей коллеги нужна она) следует:
<?xml version="1.0" encoding="utf-8"?>
<MyRoot>
<MyRequest CompletionCode="0" CustomerID="9999999999"/>
<List TotalList="1">
<Order CustomerID="999999999" OrderNo="0000000001" Status="Shipped">
<BillToAddress ZipCode="22221"/>
<ShipToAddress ZipCode="22222"/>
<Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</Order>
</List>
<Errors/>
</MyRoot>
<ns:MyNewRoot xmlns:ns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<N1:MyRequest CompletionCode="0" CustomerID="9999999999"/>
<ns:List TotalList="1">
<N2:Order CustomerID="999999999" Level="Preferred" Status="Shipped">
<N2:BillToAddress ZipCode="22221"/>
<N2:ShipToAddress ZipCode="22222"/>
<N2:Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</N2:Order>
</ns:List>
<ns:Errors/>
</ns:MyNewRoot>
Обратите внимание, что детям N2:Order также нужен N2: префикс, а также нс: префикс для остальной части элементов.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/MyRoot">
<MyNewRoot xmlns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<xsl:apply-templates/>
</MyNewRoot>
</xsl:template>
<xsl:template match="/MyRoot/MyRequest">
<xsl:element name="N1:{name()}" namespace="http://schemas.foo.com/request">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="/MyRoot/List/Order">
<xsl:element name="N2:{name()}" namespace="http://schemas.foo.com/details">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Этот не обрабатывает нс (я не мог понять это). Когда я обрабатываю через выше преобразования XSL с AltovaXML, я заканчиваю с ниже:
<MyNewRoot xmlns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<N1:MyRequest CompletionCode="0" CustomerID="9999999999"/>
<List xmlns="" TotalList="1">
<N2:Order CustomerID="999999999" Level="Preferred" Status="Shipped">
<BillToAddress ZipCode="22221"/>
<ShipToAddress ZipCode="22222"/>
<Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</N2:Order>
</List>
<Errors/>
</MyNewRoot>
Обратите внимание что N2: префикс для детей Порядка не там после преобразования XSL. Также дополнительный xmlns = "" в Заголовке заказа (по некоторым причинам). Я не мог выяснить помещение нс: префикс для остальной части элементов (как Ошибки и Список).
В первую очередь, почему я должен был бы поместить префикс для детей, если родитель уже имеет его. Разве родительское пространство имен не диктует дочерние пространства имен узлов/атрибута?
Это преобразование (всего 42 строки) :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="*">
<xsl:element name="ns:{name()}"
namespace="http://schemas.foo.com/response">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="/MyRoot">
<xsl:element name="ns:{name()}"
namespace="http://schemas.foo.com/response">
<xsl:copy-of select=
"document('')/*/namespace::*[name()='N1' or name()='N2']"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="MyRequest">
<xsl:element name="N1:{name()}"
namespace="http://schemas.foo.com/request">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="*[ancestor-or-self::Order]">
<xsl:element name="N2:{name()}"
namespace="http://schemas.foo.com/details">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному XML-документу :
<MyRoot>
<MyRequest CompletionCode="0" CustomerID="9999999999"/>
<List TotalList="1">
<Order CustomerID="999999999" OrderNo="0000000001" Status="Shipped">
<BillToAddress ZipCode="22221"/>
<ShipToAddress ZipCode="22222"/>
<Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</Order>
</List>
<Errors/>
</MyRoot>
дает желаемый результат :
<ns:MyRoot xmlns:N1="http://schemas.foo.com/request" xmlns:N2="http://schemas.foo.com/details" xmlns:ns="http://schemas.foo.com/response">
<N1:MyRequest CompletionCode="0" CustomerID="9999999999"/>
<ns:List TotalList="1">
<N2:Order CustomerID="999999999" OrderNo="0000000001" Status="Shipped">
<N2:BillToAddress ZipCode="22221"/>
<N2:ShipToAddress ZipCode="22222"/>
<N2:Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</N2:Order>
</ns:List>
<ns:Errors/>
</ns:MyRoot>
Do примечание :
Использование
и его атрибутов name
и namespace
.
Как шаблон идентичности
был преобразован в первые два шаблона преобразования - это решение было основано на том факте, что только в исключительных случаях элемент не должен находиться в нс:
пространство имен.
Как пространство имен N2:
указывается для элемента Order
или любого из его дочерних элементов.
Если вам действительно важно, какие префиксы пространств имен используются в выводе, то вы захотите использовать в своих шаблонах элементы literal-result, а не конструктор xsl:element
:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="MyRoot">
<ns:MyNewRoot>
<xsl:apply-templates/>
</ns:MyNewRoot>
</xsl:template>
<xsl:template match="MyRequest">
<N1:MyRequest>
<xsl:apply-templates select="@* | node()"/>
</N1:MyRequest>
</xsl:template>
<xsl:template match="List">
<ns:List>
<xsl:apply-templates select="@* | node()"/>
</ns:List>
</xsl:template>
<xsl:template match="Order">
<N2:Order>
<xsl:apply-templates select="@* | node()"/>
</N2:Order>
</xsl:template>
<xsl:template match="BillToAddress">
<N2:BillToAddress>
<xsl:apply-templates select="@* | node()"/>
</N2:BillToAddress>
</xsl:template>
<xsl:template match="ShipToAddress">
<N2:ShipToAddress>
<xsl:apply-templates select="@* | node()"/>
</N2:ShipToAddress>
</xsl:template>
<xsl:template match="Totals">
<N2:Totals>
<xsl:apply-templates select="@* | node()"/>
</N2:Totals>
</xsl:template>
<xsl:template match="Errors" />
</xsl:stylesheet>
Вы должны знать, что пространство имен важно, а префикс пространства имен нет. Это синтаксический сахар. Вы можете иметь несколько префиксов пространства имен, связанных с одним и тем же пространством имен -uri, или не иметь префикса пространства имен и все равно создавать элементы одного и того же типа (связанные с определенным пространством имен -uri).