簡體   English   中英

如何使用XSLT顯示經過XSD驗證的XML

[英]How to display XSD validated XML using XSLT

我已經為此奮斗了一段時間,還沒有找到明確的答案。

據我了解,我可以將數據存儲在XML文件中,使用XSD對其進行驗證,然后使用XSLT整齊地顯示數據。

但是,在嘗試執行XPath查詢以選擇希望在XSLT中顯示的數據時遇到了問題。 當我使用'.//'或'*'之類的通用選擇器時,我會得到預期的結果。 但是,當我嘗試使用更具體的選擇器時,例如:'root / responses'或其任何其他變體,沒有任何結果。

XSD已正確驗證了XML文件,因此我想我的數據至少在某種程度上是正確的。 當我刪除XML文件中的XSD引用,從而有效地刪除了數據驗證時,我的XPath查詢突然起作用了! 有什么我想念的嗎? 我嘗試將名稱空間引用添加到XSLT,但無濟於事。

我在下面介紹了XSD,示例XL和示例XSLT。 任何幫助或提示,將不勝感激!


定義結構的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>

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>

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>

一個簡單的問題:您的XML元素位於XSLT不知道的名稱空間中。

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

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

像這樣更改您的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>

請注意如何聲明名稱空間並為其指定前綴。 以后,使用該前綴引用該名稱空間中的所有節點。 exclude-result-prefixes用於確保名稱空間不會不必要地出現在輸出中。

當然,一旦您發布問題,您就會自己找到答案!

事實證明,名稱空間引用中肯定存在拼寫錯誤。 仔細檢查此帖子后:

xslt-transform-xml-with-namespaces

基本上,這是相同的問題。 (我在發布之前進行了搜索。...誠實!),我嘗試再次添加名稱空間引用,但這一次它運行得很順利!

我將名稱空間映射到前綴“ 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>

這是一個名稱空間問題。 您必須為http://foo.bar/responsecode.xsd添加名稱空間聲明,並使用該名稱空間引用元素。 更多信息可以在這里找到

因此,基本上,您將需要以下內容:

<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>

注意xsl:stylesheet的屬性中的“ xmlns:test”。 我對此進行了測試,它可以正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM