如何使用 XSLT 显示 XSD 验证的 XML

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1756652/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 12:50:27  来源:igfitidea点击:

How to display XSD validated XML using XSLT

xmlxsltxpathxsdnamespaces

提问by Robert Sirre

I've been fighting with this for some time now, and haven't been able to find a clear answer to this yet.

我已经为此奋斗了一段时间,但还没有找到明确的答案。

As I understand correctly I can store data in an XML file, validate it using an XSD and then display the data neatly using an XSLT.

正如我正确理解的那样,我可以将数据存储在 XML 文件中,使用 XSD 对其进行验证,然后使用 XSLT 整齐地显示数据。

However I've been having issues trying to perform XPath queries to select the data I wish to display in my XSLT. When I use generic selectors like './/' or '*' I get the results I'd expect. However when I try to use more specific selectors like : 'root/responses' or any other variant hereof, I get no results.

但是,我在尝试执行 XPath 查询以选择我希望在 XSLT 中显示的数据时遇到了问题。当我使用像 './/' 或 '*' 这样的通用选择器时,我得到了我期望的结果。但是,当我尝试使用更具体的选择器时,例如:'root/responses' 或任何其他变体,我没有得到任何结果。

The XML file is validated correctly by the XSD, so I guess my data is at least somewhat correct. When I remove the XSD reference in the XML file, effectively removing the data validation, my XPath queries suddenly do work! Is there something I'm missing? I've tried adding namespace references to the XSLT but to no avail.

XSD 正确验证了 XML 文件,所以我想我的数据至少在某种程度上是正确的。当我删除 XML 文件中的 XSD 引用时,有效地删除了数据验证,我的 XPath 查询突然起作用了!有什么我想念的吗?我试过向 XSLT 添加命名空间引用,但无济于事。

I've described the XSD, Sample XL and Sample XSLT below. Any help or hints would be appreciated!

我已经在下面描述了 XSD、Sample XL 和 Sample XSLT。任何帮助或提示将不胜感激!



The XSD, defining the structure, is as follows. This XSD describes a simple document, which nests three elements, and applies a restraint; the code of the responses'code must be unique.

定义结构的 XSD 如下所示。这个 XSD 描述了一个简单的文档,它嵌套了三个元素,并应用了一个约束;响应代码的代码必须是唯一的。

<?xml version="1.0" encoding="utf-8"?>
    <xs:schema id="uitext"
        targetNamespace="http://foo.bar/responsecode.xsd"
        elementFormDefault="qualified"
        xmlns:responsecodes="http://foo.bar/responsecode.xsd"
        xmlns:xs="http://www.w3.org/2001/XMLSchema">

        <xs:element name="root" type="responsecodes:rootType">
            <xs:key name="responseCode">
                <xs:selector xpath="responsecodes:responses/responsecodes:response">
                    <xs:annotation>
                        <xs:documentation>All defined responsecodes</xs:documentation>
                    </xs:annotation>
                </xs:selector>
                <xs:field xpath="@code">
                    <xs:annotation>
                        <xs:documentation>Unique responsecode</xs:documentation>
                    </xs:annotation>
                </xs:field>
            </xs:key>
        </xs:element>

        <xs:complexType name="rootType">
            <xs:sequence>
                <xs:element name="responses" minOccurs="1" maxOccurs="1" type="responsecodes:responseList">
                    <xs:annotation>
                        <xs:documentation>Defined responsecodes</xs:documentation>
                    </xs:annotation>
                </xs:element>
            </xs:sequence>
        </xs:complexType>

        <xs:complexType name="responseList">
            <xs:sequence>
                <xs:element name="response" minOccurs="0" maxOccurs="unbounded" type="responsecodes:response"/>
            </xs:sequence>
        </xs:complexType>

        <xs:complexType name="response">
            <xs:sequence>
                <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1">
                    <xs:annotation>
                        <xs:documentation>
                            Explains the use of the responsecode.
                        </xs:documentation>
                    </xs:annotation>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="code" type="xs:string" use="required">
                <xs:annotation>
                    <xs:documentation>Unique code representing the response provided.</xs:documentation>
                </xs:annotation>
            </xs:attribute>
        </xs:complexType>
    </xs:schema>

An example XML document can be as follows:

示例 XML 文档可以如下所示:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="responsecode.xsl"?>
<root xmlns="http://foo.bar/responsecode.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://foo.bar/responsecode.xsd responsecode.xsd">
    <responses>
        <response code="firstCode">
            <description>Explanation of first code</description>
        </response>
        <response code="secondCode">
            <description>Explanation of second code</description>
        </response>
        <response code="thirdCode">
            <description>Explanation of third code.</description>
        </response>
    </responses>
</root>

The test XSLT document referred to in the XML file is as follows. (This would display the codes as mentioned in a format that would resemble VS2008 enumeration definitions, but that aside)

XML文件中引用的测试XSLT文档如下。(这将以类似于 VS2008 枚举定义的格式显示提到的代码,但除此之外)

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <html><body><h2>Responses</h2>

                <xsl:for-each select="root/responses/response">
                    <xsl:choose>
                        <xsl:when test="description != ''">
                            <br/>'''&lt;description&gt;
                            <br/>'''<xsl:value-of select="description" />
                            <br/>'''&lt;/description&gt;
                        </xsl:when>
                    </xsl:choose>
                    <br/>
                    <xsl:value-of select="@code" />

                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

采纳答案by Robert Sirre

And of course as soon as you post a question, you find an answer yourself!

当然,一旦您发布问题,您就会自己找到答案!

It turns out there must have been a typo in the namespace reference. After double checking this post:

事实证明,命名空间引用中一定有错别字。仔细检查这篇文章后:

xslt-transform-xml-with-namespaces

xslt-transform-xml-with-namespaces

Which basically turns out to be the same question. (I searched before posting....honest!), I tried adding a namespace reference again, and this time it worked flawlessly!

这基本上是同一个问题。(我在发帖之前搜索过......诚实!),我再次尝试添加命名空间引用,这次它完美无缺!

I mapped the namespace to the prefix 'nsm' (NameSpaceMapping) and voilá!

我将命名空间映射到前缀“nsm”(NameSpaceMapping),瞧!

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:nsm="http://foo.bar/responsecode.xsd">
    <xsl:template match="/">
        <html><body><h2>Responses</h2>

                        <xsl:for-each select="nsm:root/nsm:responses/nsm:response">
                                <xsl:choose>
                                        <xsl:when test="nsm:description != ''">
                                                <br/>'''&lt;description&gt;
                                                <br/>'''<xsl:value-of select="nsm:description" />
                                                <br/>'''&lt;/description&gt;
                                        </xsl:when>
                                </xsl:choose>
                                <br/>
                                <xsl:value-of select="@code" />

                        </xsl:for-each>
                </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

回答by Tomalak

Simple problem: Your XML elements are in a namespace your XSLT knows nothing about.

简单的问题:您的 XML 元素位于您的 XSLT 一无所知的名称空间中。

<root xmlns="http://foo.bar/responsecode.xsd">
  <responses>
    <!-- ... -->
  </responses>
</root>

puts your <root>and all descendant elements into the "http://foo.bar/responsecode.xsd"namespace.

将您<root>和所有后代元素放入"http://foo.bar/responsecode.xsd"命名空间。

Change your XSL like this:

像这样更改您的 XSL:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:foo="http://foo.bar/responsecode.xsd"
  exclude-result-prefixes="foo"
>
  <xsl:template match="/">
    <html>
      <body>
        <h2>Responses</h2>
        <xsl:for-each select="foo:root/foo:responses/foo:response">
          <!-- ... -->
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Note how the namespace is declared and given a prefix. Later, all nodes in that namespace are referred to using that prefix. exclude-result-prefixesis used to make sure the namespace does not appear in the output unnecessarily.

请注意命名空间是如何声明的并为其赋予前缀。稍后,使用该前缀引用该名称空间中的所有节点。exclude-result-prefixes用于确保命名空间不会不必要地出现在输出中。

回答by Welbog

It's a namespace problem. You'll have to add a namespace declaration for http://foo.bar/responsecode.xsd, and refer to elements using that namespace. More info can be found here.

这是一个命名空间问题。您必须为 ,添加命名空间声明http://foo.bar/responsecode.xsd,并引用使用该命名空间的元素。更多信息可以在这里找到

So basically you'll need something like this:

所以基本上你需要这样的东西:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:test="http://foo.bar/responsecode.xsd">
  <xsl:template match="/">
    <html>
      <body>
        <h2>Responses</h2>

        <xsl:for-each select="test:root/test:responses/test:response">
          <xsl:choose>
            <xsl:when test="test:description != ''">
              <br/>'''&lt;description&gt;
              <br/>'''<xsl:value-of select="test:description" />
              <br/>'''&lt;/description&gt;
            </xsl:when>
          </xsl:choose>
          <br/>
          <xsl:value-of select="@code" />

        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Note the "xmlns:test" in the xsl:stylesheet's attributes. I gave this a test and it works.

注意xsl:stylesheet的属性中的“xmlns:test” 。我对此进行了测试,并且有效。