XSI命名空间复制到结果序列

时间:2018-05-11 17:00:33

标签: xml xslt xsd xslt-3.0

我有一个包含大量查找的XML文件。以下简化版本:

<?xml version="1.0" encoding="UTF-8"?>
<Parties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="/usr/local/share/xml/schema/quantile/Parties.xsd">
    <Party name="Bens Birthday">
        <ZIP>AB1234</ZIP>
        <EMAIL>foo@bar.com</EMAIL>
        <ATTENDEES>
            <ATTENDEE>Bob</ATTENDEE>
            <ATTENDEE>David</ATTENDEE>
        </ATTENDEES>
    </Party>
</Parties>

我写了一个简单的XSD来验证这些数据:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Parties">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Party" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="ZIP" minOccurs="0" maxOccurs="1" type="xs:string"/>
                            <xs:element name="EMAIL" minOccurs="0" maxOccurs="1" type="xs:string"/>
                            <xs:element name="ATTENDEES" minOccurs="0" maxOccurs="1">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="ATTENDEE" minOccurs="1" maxOccurs="unbounded" type="xs:string"/>
                                    </xs:sequence>
                                </xs:complexType>
                             </xs:element>
                        </xs:sequence>
                        <xs:attribute name="name" type="xs:string" use="required"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

这很有效。

我正在将XML文件加载到XSLT中并将其用作转换中的查找。

<xsl:variable name="party-details" select="document($party-file)/Parties"/>
<xsl:variable name="party-map" select="$party-details/Party[@name='Bens Birthday']"/>

当我在询问文本节点时,这很有效:

<FOO>{$party-map/EMAIL}</FOO>

但如果我尝试对序列做同样的事情:

<xsl:sequence select="$party-map/ATTENDEES/ATTENDEE"/>

我从Party XML文件继承命名空间定义:

<Parties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="/usr/local/share/xml/schema/quantile/Parties.xsd">

产生如下输出:

<ATTENDEE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Bob</ATTENDEE>

显然,如果我从Party XML文件中删除xmlns:xsixsi:noNamespaceSchemaLocation,问题就会消失......但是我没有验证它。

最终这会破坏我的XSLT输出验证,因为xsi元素上不允许ATTENDEE定义。

我看到这里发生了什么 - Parties的所有孩子都继承了命名空间xmlns:xsi,所以当我将ATTENDEE序列拼接到我的XSLT输出中时,缺少xsi XSLT中的定义意味着处理器将其添加进来。我认为它不会对文本节点执行此操作,因为它们没有命名空间的概念,只有该元素才能执行此操作。

我可以通过在XSLT中的输出元素和ATTENDEE的父元素上定义xmlns:xsi来解决问题。

这仍然限制了我的输出格式。感觉我应该能够删除命名空间,但我对如何继续进行了解决。

有什么想法吗?或者,如果有人可以断然说这是不可能的,那么任何其他建议 - 比如使用DTD,或者完全离开XML架构,并在XSLT中进行验证?我现在在猜!

1 个答案:

答案 0 :(得分:1)

请勿使用xsl:sequence,然后使用xsl:copy-of copy-namespaces="no",例如

<xsl:copy-of select="Parties/Party[@name = 'Bens Birthday']/ATTENDEES" copy-namespaces="no"/>

https://xsltfiddle.liberty-development.net/bdxtpU使用您的示例作为主要输入,但当然您也可以对<xsl:copy-of select="$party-map/ATTENDEES/ATTENDEE" copy-namespaces="no"/>执行此操作。