2012-06-28 122 views
1

我是一名XML初學者。我使用lxml python庫來處理SAML文檔,但是我的問題與SAML或SSO並不真正相關。刪除屬於特定名稱空間的所有XML元素

非常簡單,我需要刪除此XML文檔中屬於「ds」命名空間的所有元素。我看着Xpath Search,我看着findall(),但是我不知道如何使用命名空間。

的原始文件看起來是這樣的:

<Response IssueInstant="dateandtime" ID="redacted" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <saml:Issuer>redacted.com</saml:Issuer> 
    <Status> 
    <StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> 
    </Status> 
    <saml:Assertion Version="2.0" IssueInstant="redacted" ID="redacted"> 
    <saml:Issuer>redacted</saml:Issuer> 
    <ds:Signature> 
     <ds:SignedInfo> 
     <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
     <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 
     <ds:Reference URI="#redacted"> 
      <ds:Transforms> 
      <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> 
      <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
      </ds:Transforms> 
      <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
      <ds:DigestValue>redacted</ds:DigestValue> 
     </ds:Reference> 
     </ds:SignedInfo> 
     <ds:SignatureValue>redacted==</ds:SignatureValue> 
     <ds:KeyInfo> 
     <ds:X509Data> 
      <ds:X509Certificate>certificateredacted=</ds:X509Certificate> 
     </ds:X509Data> 
     <ds:KeyValue> 
      <ds:RSAKeyValue> 
      <ds:Modulus>modulusredacted==</ds:Modulus> 
      <ds:Exponent>AQAB</ds:Exponent> 
      </ds:RSAKeyValue> 
     </ds:KeyValue> 
     </ds:KeyInfo> 
    </ds:Signature> 
    <saml:Subject> 
     <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">subject_redacted</saml:NameID> 
     <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> 
     <saml:SubjectConfirmationData NotOnOrAfter="date_time_redacted" Recipient="https://website.com/redacted"/> 
     </saml:SubjectConfirmation> 
    </saml:Subject> 
    <saml:Conditions NotOnOrAfter="date_time_redacted" NotBefore="date_time_redacted"> 
     <saml:AudienceRestriction> 
     <saml:Audience>audience_redacted</saml:Audience> 
     </saml:AudienceRestriction> 
    </saml:Conditions> 
    <saml:AuthnStatement AuthnInstant="date_time_redacted" SessionIndex="date_time_redacted"> 
     <saml:AuthnContext> 
     <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef> 
     </saml:AuthnContext> 
    </saml:AuthnStatement> 
    <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
     <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" Name="attribute_name_redacted"> 
     <saml:AttributeValue xsi:type="xs:string">attribute=redacted</saml:AttributeValue> 
     </saml:Attribute> 
     <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" Name="attribute_name_redacted"> 
     <saml:AttributeValue xsi:type="xs:string">value_redacted</saml:AttributeValue> 
     </saml:Attribute> 
    </saml:AttributeStatement> 
    </saml:Assertion> 
</Response> 

我要的是一個文件,看起來像這樣:

<Response IssueInstant="dateandtime" ID="redacted" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <saml:Issuer>redacted.com</saml:Issuer> 
    <Status> 
    <StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> 
    </Status> 
    <saml:Assertion Version="2.0" IssueInstant="redacted" ID="redacted"> 
    <saml:Issuer>redacted</saml:Issuer> 
    <saml:Subject> 
     <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">subject_redacted</saml:NameID> 
     <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> 
     <saml:SubjectConfirmationData NotOnOrAfter="date_time_redacted" Recipient="https://website.com/redacted"/> 
     </saml:SubjectConfirmation> 
    </saml:Subject> 
    <saml:Conditions NotOnOrAfter="date_time_redacted" NotBefore="date_time_redacted"> 
     <saml:AudienceRestriction> 
     <saml:Audience>audience_redacted</saml:Audience> 
     </saml:AudienceRestriction> 
    </saml:Conditions> 
    <saml:AuthnStatement AuthnInstant="date_time_redacted" SessionIndex="date_time_redacted"> 
     <saml:AuthnContext> 
    <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef> 
     </saml:AuthnContext> 
    </saml:AuthnStatement> 
    <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
     <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" Name="attribute_name_redacted"> 
     <saml:AttributeValue xsi:type="xs:string">attribute=redacted</saml:AttributeValue> 
     </saml:Attribute> 
     <saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" Name="attribute_name_redacted"> 
     <saml:AttributeValue xsi:type="xs:string">value_redacted</saml:AttributeValue> 
     </saml:Attribute> 
    </saml:AttributeStatement> 
    </saml:Assertion> 
</Response> 

回答

2

您可以在使用XPath與//namespace:*命名空間元素,例如:

doc_root.xpath('//ds:*', namespaces={'ds': 'http://www.w3.org/2000/09/xmldsig#'}) 

因此,除去所有的孩子在這個命名空間,你可以使用的東西如下所示:

def strip_dsig(doc_root): 
    nsmap={'ds': 'http://www.w3.org/2000/09/xmldsig#'} 
    for element in doc_root.xpath('//ds:*', namespaces=nsmap): 
     element.getparent().remove(element) 
    return doc_root 
+0

謝謝!這很好,比XSLT簡單一些。 –

0

這是很容易與一個XSL樣式表做。這可能是你最好的方法。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
exclude-result-prefixes="ds"> 
<!-- no_ds.xsl --> 

<xsl:template match="node()|@*"> 
    <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy> 
</xsl:template> 

<xsl:template match="ds:*"><xsl:apply-templates select="*"/></xsl:template> 
<xsl:template match="@ds:*"/>  
</xsl:stylesheet> 

您可以使用xsltproc(對於libxml2的)或等效命令行運行此:

xsltproc -o directoryname/ no_ds.xsl file1.xml file2.xml 

這將創建目錄名/ file1.xml和目錄名/ file2.xml沒有DS命名空間。

你也可以用lxml使用lxml's libxslt2 bindings來做到這一點。

no_ds_stylesheet = etree.parse('no_ds.xsl') 
no_ds_transform = etree.XSLT() 

# doc_to_transform is an Element or ElementTree 
# from etree.fromstring(), etree.XML(), or etree.parse() 
no_ds_doc = no_ds_transform(doc_to_transform) 

#no_ds_doc is now another ElementTree doc, the result of the XSLT transform. 
#You can reuse the no_ds_transform object multiple times (and should if you can) 

no_ds_doc2 = no_ds_transform(doc_to_transform2) 

由於XSLT文件的XML文檔,你甚至可以創建使用lxml的動態自定義XSLT樣式表,並定義要動態忽略的命名空間。 (作爲練習留給讀者。)

+0

謝謝!我測試了你的答案。它完美的作品。 –

相關問題